Skip to content
← escentmachine field notes

Why JSON Rejects NaN and Infinity, and How to Handle Them

On this page
AI-generated illustration; not taken on location · Conceptual diagram showing the boundary between application numbers, JSON numbers, and quoted strings.
AI-generated illustration; not taken on location · JSON number grammar excludes nonfinite numeric tokens; quotation marks change a label into a string.AI-generated illustration

JSON excludes NaN, Infinity, and -Infinity as numbers because their spellings do not fit its number grammar. Holding one of these values in application memory does not give it a valid numeric representation in JSON text. Quoting the label creates a string and requires an application agreement about its meaning.

The practical decision is what the receiver needs to know. An unavailable reading might become null under an agreed contract. Another application might need to preserve each exceptional state through descriptive strings or tagged objects. A field that requires a permitted number may instead require rejection before transmission.

Start by finding the original values and recording their locations. Then inspect the proposed output and the receiver’s intended interpretation. The examples below are representation proposals and validation requirements awaiting execution in the intended environment; they do not establish the behavior of any particular serializer.

Why these runtime values have no JSON number spelling

JSON numbers use decimal digits, with an integer component and optional fraction or exponent components. Spellings such as 12, -12.5, and 3E2 illustrate those forms. The number grammar explicitly excludes values such as NaN and Infinity.

Negative infinity encounters the same boundary. A leading minus sign does not make the complete token -Infinity fit the permitted grammar. None of these proposed fragments therefore contains a permitted JSON number in the reading field:

{"reading":NaN}
{"reading":Infinity}
{"reading":-Infinity}

Compare them with a quoted label:

{"reading":"Infinity"}

Here, the value is a string. Its spelling can be used in a proposed application convention, but quotation marks do not create a JSON number representing infinity. The receiving application must explicitly agree to interpret that string as an exceptional state.

This distinction gives you a useful first diagnostic question: is the problem an unpermitted numeric token, or a permitted string whose meaning the receiver has not agreed to accept? The remedies differ. Changing syntax can produce acceptable text while leaving the application contract unresolved.

Separate parsing errors from serialization choices

Trace three things separately: the value held by the application, the text prepared for transmission, and the value the receiver is expected to understand. Record the original state before choosing a conversion.

For an application reading containing NaN, consider these hypothetical serialization policies. They describe possible design choices, without asserting that a particular library implements them.

Proposed policy Intended result Consequence to inspect
Reject the value Stop with a validation failure Does the report identify the location?
Replace it with null {"reading":null} Does the receiver accept the intended unavailable state?
Emit the unquoted label {"reading":NaN} The text is outside JSON’s number grammar

A rejection before output and an invalid token in transmitted text occur at different stages. An error report should make that distinction clear so the developer knows whether to inspect input validation or the generated text.

The null proposal illustrates a separate issue. Even if the output passes a JSON syntax check, the receiver cannot determine from null alone that the original value was NaN. The proposed conversion has removed that distinction.

For a concrete investigation, write down the application value, the exact emitted text, and the required receiver interpretation. An output that satisfies only the middle step has not yet demonstrated that the exchange preserves the information the application needs.

Find nonfinite values and report their paths

Design validation to inspect the original application values before any replacement occurs. Use a numeric classification operation whose behavior you have verified in the chosen language’s documentation. Confirm that it distinguishes NaN, positive infinity, and negative infinity from the finite numbers your contract accepts.

NaN values do not compare equal to themselves. Equality with NaN is therefore unsuitable as the basis for identifying that state. This fact also does not supply a complete detector for both infinity cases; verify those explicitly.

Specify the walk before choosing an API

For an initial design limited to acyclic arrays and plain objects, use this language-neutral procedure:

  1. If the current value is numeric, apply the verified numeric check. Record its path and exceptional state when appropriate.
  2. If it is an array, visit its elements and extend each path with the element index.
  3. If it is a plain object, visit its property values and extend their paths with the property names.
  4. Leave ordinary strings and other accepted values unchanged.

For simple property names, adopt paths such as metrics[1]. Use $ as the reporting label when the entire input is an offending value. These are proposed reporting conventions; define additional notation before handling keys containing punctuation.

Consider this application-value sketch, which is not JSON text:

{
  metrics: [NaN, Infinity, -Infinity, 0],
  note: "Infinity"
}

The acceptance requirements for the proposed validator are:

Input location Required finding
metrics[0] Report the NaN state
metrics[1] Report positive infinity
metrics[2] Report negative infinity
metrics[3] No nonfinite finding
note Preserve the ordinary string

Also require a root NaN value to produce a finding at $, while a root string "NaN" remains ordinary text. These are cases to verify after implementation, rather than claimed results from an executed detector.

Choose null when the receiver accepts an unavailable value

Choose null when the receiving contract explicitly permits it and assigns it a suitable meaning. For example, the applications could agree that an unavailable reading is represented as:

{"reading":null}

Confirm what “unavailable” means for this field. Should the receiver omit the reading from a calculation, display an unavailable state, or request corrected input? Those are application decisions that acceptable JSON syntax cannot settle.

A single null replacement cannot retain the distinction among NaN, positive infinity, negative infinity, and a null already present in the input. Once all four share the same representation, that field alone cannot reveal the original state.

If those distinctions matter, consider companion status information. A proposed representation for positive infinity is:

{"reading":null,"status":"positive-infinity"}

The receiver must agree to both the extra field and the status vocabulary. Define a separate status for an original null if its origin must remain distinguishable.

Review the complete mapping before adopting it: what would each exceptional state become, and what would an existing null become? If the answer deliberately combines states that the receiver treats identically, null may suit the contract. If the receiver needs different decisions for those states, retain the necessary information explicitly.

Choose descriptive strings when exceptional states must survive

Descriptive strings can preserve the three exceptional states when the receiver explicitly reserves and interprets those labels. One proposed representation is:

{"readings":["NaN","Infinity","-Infinity"]}

Under this agreement, "NaN" represents the original NaN state, "Infinity" represents positive infinity, and "-Infinity" represents negative infinity. These meanings belong to the proposed application contract. The transmitted values are strings.

This conversion changes the field’s type. Confirm that the receiver permits these strings in the relevant positions and defines what happens when it encounters each one. A field described only as accepting numbers needs a revised agreement before this representation can be adopted.

Check whether the labels collide with ordinary text

Suppose the application already accepts the ordinary string "Infinity". Converting a numeric infinity to the same string makes the two origins indistinguishable. Ask whether reserving that label would interfere with legitimate text.

When the distinction matters, consider a tagged representation:

{"reading":{"kind":"nonfinite","label":"Infinity"}}

This is a proposed object shape requiring receiver agreement. Define which labels it permits and how ordinary text is represented. Check whether existing application data could already use the same shape.

A useful acceptance case places a converted infinity beside an original "Infinity" string. Specify how the receiver should distinguish them. If the representation cannot support a distinction the application requires, revise the contract before implementing the conversion.

Reject invalid numeric states when the contract requires numbers

Choose rejection when the field requires a permitted number and the contract accepts neither null nor an alternative representation. Detect the offending location before transmission so the caller can identify what needs correction.

A proposed application flow is to collect findings, stop preparation of the affected payload when findings exist, and return a structured validation result. For example, the application could report:

{"error":"nonfinite-number","path":"metrics[1]","state":"Infinity"}

The field names, error label, and wording above are application design choices. They do not describe a library exception or guarantee any serializer’s behavior.

Decide whether the caller needs the first offending location or every location. For the earlier example, reporting all three paths could let the caller address the complete set in one correction. Keep the original values available during validation so an error can distinguish the states when useful.

Verify the enforcement mechanism

Before relying on a serializer setting, check its approved documentation for nonfinite input handling, failure reporting, and whether it supplies locations. Establish those details for the actual implementation instead of inferring them from an option name.

Make rejection actionable: identify the path, state the field’s requirement, and explain which correction or agreed representation the caller may supply. A contract that requires numbers should not silently acquire a null or string conversion merely to produce output.

Keep JSON syntax, numeric range, and preserved meaning separate

Three checks answer different questions: does the text follow JSON syntax, can the receiver support the required numeric range and precision, and does the representation retain the meaning the application needs?

1E400 makes the distinction concrete. It is a permitted JSON number spelling, while its magnitude may create interoperability problems. JSON permits implementations to limit the range and precision of accepted numbers. Valid syntax therefore does not establish that a particular receiver can retain the intended value.

Investigate the receiver’s documented range handling separately from the invalid tokens NaN, Infinity, and -Infinity. Ask how values beyond its supported range are reported and what the application should do next.

Proposed text value Syntax category Contract or receiver check
12.5 Permitted number spelling Does it satisfy the field’s requirements?
NaN Unpermitted numeric token Which conversion or rejection policy applies?
Infinity Unpermitted numeric token Must positive infinity remain distinguishable?
-Infinity Unpermitted numeric token Must negative infinity remain distinguishable?
"Infinity" String Is it ordinary text or an agreed reserved label?
null Null Was it original data or a replacement, and does that matter?
1E400 Permitted number spelling Can the receiver support the required magnitude?

Build acceptance cases from this matrix. Include finite input, all three nonfinite states, an existing null, an ordinary string matching a proposed label, and the large exponent example.

For each case, specify the original value, intended output or validation failure, and required receiver interpretation. Then verify those expectations in the implementation. Inspecting both the emitted text and the receiving result makes changes in syntax and changes in meaning visible.

Previous note
Next note