Key takeaway
A successful parse is not a preservation check. Find repeated names in each original JSON object before treating the receiving map as the complete source record.
Check the text before the dictionary
An export owner sees a job with one status field. The recipient also sees one status field, so the transfer looks faithful. Yet the original text might have contained status twice. If the receiving parser keeps one occurrence, a comparison made only after parsing cannot show what disappeared. The first decision is whether the file preserves a single unambiguous value for each field, not whether the software opened it.
RFC 8259 recommends unique names within a JSON object and describes differing receiver behavior for repetitions. It does not make one universal last-value rule an interoperability guarantee. Python’s json documentation supplies a concrete implementation example: its default decoder accepts repeated names and uses the last pair. That documented behavior is a reason to inspect the actual receiving path, rather than assume every parser rejects the problem.
One fictional job, two statuses
In this hypothetical fixture, the source text has job J-17, followed by status open and another status closed inside the same object. A default Python decode exposes closed. This is not a two-event history: there are no separate event identities or times. It is also not evidence that closed was the intended correction. The source operator has to explain why both pairs were emitted.
The table describes proposed receiving decisions for invented inputs. A repeated business identifier across two array items is a different case from repeating a member name inside one object. Treating both as duplicate keys would erase legitimate observations. Keep the location of the conflict, including its enclosing object, in the internal exception record.
| Illustrative input | Receiving observation | Decision |
|---|---|---|
| One object: status open; status closed | A receiver may expose only closed | Hold this object; preserve original text |
| One object: status open; nested review.status closed | Different enclosing objects | Check each field’s defined meaning |
| Two array items with job J-17 | Two separate object instances | Apply the event-identity rule separately |
| One object: status closed only | No repeated status in this fixture | Continue other content and schema checks |
Keep a diagnostic before irreversible conversion
Have the technical owner run a member-aware check while the original text is still available in an authorized environment. The diagnostic should identify the package, record boundary, object path, repeated name and occurrence count. A normal dictionary created after a last-value decode is too late to recover the overwritten pair. Preserve the original artifact according to its existing access and retention rules.
Python documents object_pairs_hook as a way to alter object handling. That is a capability to evaluate, not a promise that one option repairs an entire pipeline. Confirm that the chosen checker reaches nested objects and that any subsequent conversion is subject to the same policy. A source-side exporter, a message gateway and a receiving loader can each introduce a different interpretation boundary.
Make the rejection rule testable
Write a small synthetic fixture set containing an ordinary object, a repeated name with equal values, a repeated name with conflicting values, nested objects and an array of separate events. State the expected outcome before running it. Even identical repeated values deserve a documented policy: accepting them today can conceal an exporter defect that produces conflicting values tomorrow.
Use the same checker version and settings on both ends of the proposed transfer. Record whether the operation rejects the entire package, withholds the affected objects or permits a specifically reviewed exception. The method should fail visibly. Quietly selecting the first or last pair and labelling the result corrected would invent a source decision. If the owner supplies a corrected export, retain its separate version and explanation.
Describe the finding without redistributing the record
For the fictional J-17 case, the bounded conclusion is that the inspected source object has an unresolved status conflict. The recipient may test the synthetic fixture and the policy without receiving the company’s actual narrative or identifiers. A metadata summary can state how many inspected objects were affected and which check was used; it must also state the inspection’s coverage.
Put the unresolved field and responsible exporter owner in the inventory. A source explanation or corrected version is the next useful decision. This check does not validate whether closed means a documented resolution, and a clean member-name audit does not approve disclosure. Keep the representation finding separate from outcome interpretation and any later sample or licensing permission.