A number is an optional sign (- or +) followed by Infinity, NaN, a hex integer, or a decimal number.

Hex integers

0x or 0X, then one or more hex digits.

Decimal numbers

The classic JSON shape (no leading zeros, optional fraction, optional exponent), plus a leading-dot form (.5) and a trailing-dot form (5.).

The digit rules the decimal form builds on:

Exact lexemes

The library remembers each number exactly as written, so on rewrite:

  • 1.50 stays 1.50 (not 1.5),
  • 0xFF stays 0xFF (not 255),
  • Infinity stays Infinity,
  • 1e3 stays 1e3.

Number stores the parsed double, the original lexeme, and a Kind (Decimal / Hex / Infinity / NegativeInfinity / NaN). setValue() regenerates the lexeme via std::to_chars and accepts non-finite values. Note: asInteger() goes through double, so integer values beyond 2^53 keep their lexeme but lose precision on that call.

Converting to strict JSON

Plain JSON has no Infinity / -Infinity / NaN and no hex. The Json writer dialect rewrites hex lexemes to decimal and throws std::domain_error on a non-finite value; fson-check --json catches that and reports it as a write failure (exit 2). The Json5 dialect keeps all of them verbatim. See Converting to JSON / JSON5.