A JSON object can repeat a field name, but converting its pairs directly to a dict discards an earlier value.
Python JSON duplicate keys: reject ambiguous object fields
Operation contract
The import receives a bounded document and asks the decoder for each object as ordered pairs. The hook rejects a repeated name at any nesting level before a dict can silently replace the first value. The accepted receipt retains its integer amount. A duplicate amount is rejected even if both spellings carry the same value.
Failure and ownership boundary
Limit bytes before decoding, not after constructing a string. This hook rejects duplicate names but does not validate the complete receipt schema, maximum nesting, or nonstandard numeric tokens. Python JSON validation: reject duplicate members and non-integer amounts, Python JSON Lines: cap line bytes and validate the whole batch before returning it and Python UTF-8 imports: reject malformed bytes and unexpected BOMs belong around this decoder.
Working program
import json
def unique_object(pairs):
result = {}
for name, value in pairs:
if name in result:
raise ValueError("duplicate field")
result[name] = value
return result
def receipt_document(payload):
if type(payload) is not str or len(payload) > 200:
raise ValueError("document length")
return json.loads(payload, object_pairs_hook=unique_object)
print(receipt_document('{"receipt":{"id":"R41","minor":125}}'))
try:
receipt_document('{"receipt":{"minor":125,"minor":0}}')
except ValueError:
print("duplicate rejected")Output
{'receipt': {'id': 'R41', 'minor': 125}}
duplicate rejectedCosts and limits
Decoding and duplicate checks take O(n) expected time and O(n) retained structure for n input characters. The small character cap is a fixture limit, not a network reception limit.
Common Mistakes
- Ordinary decoding has already lost duplicate-name evidence.
- Reject bytes before decoding and validate the resulting schema afterward.
Connected lessons
Python JSON validation: reject duplicate members and non-integer amounts, Python JSON Lines: cap line bytes and validate the whole batch before returning it, Python UTF-8 imports: reject malformed bytes and unexpected BOMs.
