Batu Lab NotesPractical developer guides

Reject NaN in a local JSON fixture

By Batu ยท English technical notes

Also published in our primary archive.

Reject NaN in a local JSON fixture

To reject NaN while decoding JSON in Python, provide parse_constant to json.loads and raise from that callback. Python calls it for the non-standard tokens NaN, Infinity, and -Infinity, so one small function can make those tokens invalid for this decode.

The in-memory fixture is the exact text NaN. Default json.loads accepts it and returns a floating-point NaN, although that token is outside the JSON specification. Because NaN is unequal to itself, value != value is a compact assertion for this particular decoded value. The first line makes the contrasting default behavior visible without depending on a platform-specific representation of NaN.

reject_non_finite raises ValueError('non-finite number') whenever the parser invokes it. The try block demonstrates the correction: the same source does not produce a usable value under this narrow policy. It does not impose a document-size limit, restrict ordinary finite numbers, or validate a surrounding object schema. If the fixture could contain Infinity or -Infinity, the same callback rejects those tokens too.

The json documentation describes both the decoder's default handling of non-finite values and parse_constant as the customization point for rejecting them. No newer API is required here: parse_constant predates the Python 3.1 addition of object_pairs_hook; current supported Python versions provide it.

AI assistance disclosure: This article was drafted with AI assistance and verified with the synthetic fixture shown.

Example

import json

source = "NaN"


def reject_non_finite(token):
    raise ValueError("non-finite number")


default_value = json.loads(source)
assert default_value != default_value
print("default is nan:", default_value != default_value)

try:
    json.loads(source, parse_constant=reject_non_finite)
except ValueError as error:
    print("validated:", error)

Expected output:

default is nan: True
validated: non-finite number