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 inputReceiving observationDecision
One object: status open; status closedA receiver may expose only closedHold this object; preserve original text
One object: status open; nested review.status closedDifferent enclosing objectsCheck each field’s defined meaning
Two array items with job J-17Two separate object instancesApply the event-identity rule separately
One object: status closed onlyNo repeated status in this fixtureContinue 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.

Tools for this decision

Data inventory builder →Diligence question builder →