Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python JSON validation: reject duplicate members and non-integer amounts

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

JSON decoding turns text into Python values; validating those values against an application schema is a separate step.

Download Python source kit

Operation contract

The receipt decoder uses an object-pairs hook to reject duplicate member names before a dictionary can overwrite them. It accepts exactly the amount_minor member and requires a positive integer, excluding bool. The program rejects both a boolean amount and two repeated amount members instead of letting each input become a plausible receipt.

Failure and ownership boundary

JSON input can consume memory before application validation runs, so cap incoming bytes or text before decoding. This fixture caps text length and accepts a flat one-field shape; it is not a general nested-document resource sandbox. Python strings and bytes: reject decoding errors before parsing records happens earlier, while Python dataclasses: frozen fields require an immutable value model can provide a later internal representation.

Working program

python
import json

def unique_members(pairs):
    values = {}
    for key, value in pairs:
        if key in values:
            raise ValueError("duplicate member")
        values[key] = value
    return values

def receipt_amount(text):
    if len(text) > 1024:
        raise ValueError("document too long")
    values = json.loads(text, object_pairs_hook=unique_members)
    if not isinstance(values, dict) or set(values) != {"amount_minor"}:
        raise ValueError("receipt shape required")
    amount = values["amount_minor"]
    if type(amount) is not int or amount <= 0:
        raise ValueError("positive integer amount required")
    return amount

print(receipt_amount('{"amount_minor":125}'))
for payload in ['{"amount_minor":true}', '{"amount_minor":1,"amount_minor":2}']:
    try:
        receipt_amount(payload)
    except ValueError:
        print("document rejected")

Output

Output
125
document rejected
document rejected

Costs and limits

Decoding n bounded characters has input-proportional work and retains the decoded graph. The length cap does not define a general depth limit; deployments must choose broader limits for broader schemas.

Common Mistakes

  • Parsing is not schema validation.
  • Reject duplicate members before overwriting loses their evidence.

Connected lessons

Python dictionaries: insertion order and duplicate-key replacement, Python strings and bytes: reject decoding errors before parsing records, Python dataclasses: frozen fields require an immutable value model.

Apply this boundary

Flask JSON API: reject unknown fields, booleans and oversized bodies.

Related Python operation checks

Python tomllib: parse configuration and validate its schema, Mypy static checks: annotations do not validate runtime payloads.

Check the next state boundary

Python JSON Lines: cap line bytes and validate the whole batch before returning it.

Follow the service contract

Python HMAC envelopes: authenticate exact bytes and separate replay policy.

Follow the integrity boundary

Python JSON duplicate keys: reject ambiguous object fields, Python project: validate a JSONL batch before one SQLite commit.

python
json-validation
Storage details