You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A parse_constant hook written to the json module's contract breaks on -NaN, because pyjson5 passes the signed spelling to the hook instead of normalizing it:
json's documented contract only ever passes 'NaN', 'Infinity', or '-Infinity' to parse_constant, so code written against it assumes a closed set. -NaN is legal JSON5, so this is reachable with perfectly ordinary input.
The inconsistency is especially visible next to the + spelling, which already arrives normalized (the parser drops the plus sign):
json5.loads('+NaN', parse_constant=HOOK) # ok — hook receives 'NaN'
Two possible resolutions:
normalize like the default parser does (_fp_constant_parser already handles -NaN via float('-nan')), so hooks receive 'NaN' for both NaN and -NaN, or
keep passing the literal but document it next to the existing parse_int caveat in the load/loads/parse docstrings (the docstrings already warn that parse_int sees 0x… spellings).
The first keeps drop-in compatibility with json-shaped hooks, which I suspect is worth more given the library already mirrors json's API so closely.
Agreed — since -NaN is legal JSON5 and the hook sees the spelling as written, documenting the contract (rather than normalizing) keeps the parser lossless. I've sent #157 with the docstring updates: a parse_constant bullet next to the existing parse_int caveat in load()/loads(), and the lettered list in parse() extended to match. Docstrings only, no behavior changes.
Activity
dpranke commentedon Nov 2, 2026
Actually, I think the second resolution is better. A
parse_constanthook should have to accept-NaNsince it is legal JSON5.I.e., I think the code is correct but the documentation is buggy and should be fixed.
Document the parse_constant -NaN caveat alongside parse_int
rahul05ranjan commentedon Nov 2, 2026
Agreed — since
-NaNis legal JSON5 and the hook sees the spelling as written, documenting the contract (rather than normalizing) keeps the parser lossless. I've sent #157 with the docstring updates: aparse_constantbullet next to the existingparse_intcaveat inload()/loads(), and the lettered list inparse()extended to match. Docstrings only, no behavior changes.Document the parse_constant -NaN caveat alongside parse_int (#157)