Files
json/docs/mkdocs/docs/api/basic_json_view/number_token.md
T
Niels Lohmann 94331d1050 Document that read() must not be given a view of the document itself (#6086)
* Document that read() must not be given a view of the document itself

basic_json_document::read() releases the previous text, the decoded
strings and the edits before it parses its input. An input that points
into them (source(), get_string(), number_token(), or a string of an
edited document) is read after its memory was cleared or freed.

A guard that copies such input costs about 1 ns per read() (5 % of a
read of a 7-byte input), which this API exists to avoid, so state the
precondition in read.md, lifetime.md and the pages of the views that
hand out such strings instead, and show how to copy the string first.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

* Assert in debug builds that read() is not given its own text

read() releases the document's text, decoded strings, owned image and
edits before it parses, so an input that points into them is read after
release. Without NDEBUG, read() now asserts that a borrowed input, a
copied contiguous input and (before C++17) a string_ref input are not
held by the document: its owned text, its decoded strings, an owned
image, and the current buffer of edited strings. Release builds keep
the documented precondition without a check, which would cost 2-4.5 %
per read() of a small message.

JSON_ASSERT is undefined at the end of json.hpp, so the view uses
assert() through a new internal NLOHMANN_VIEW_ASSERT.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>

---------

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-11-11 22:36:17 +01:00

3.6 KiB

nlohmann::basic_json_view::number_token

string_view_t number_token() const;

Returns the number exactly as it appears in the source text, without parsing or rounding it.

Return value

The number's token text, as a string_view_t into the document's source() text — for example #!cpp "1.50", #!cpp "1E2", #!cpp "-0", or an integer literal with more digits than any number type holds (such as a 30-digit integer, which get<T>() and materialize() can only represent approximately, as a number_float_t).

Exception safety

Strong guarantee: there are no changes to the view or the document it refers to.

Exceptions

Throws type_error.302 if the value is not a number; example: "type must be number, but is string".

As for BasicJsonType, with JSON_DIAGNOSTICS the exception names the JSON Pointer path of the value within the document, and with JSON_DIAGNOSTIC_POSITIONS its bytes in the source text (when materialize() sets them).

Complexity

Constant.

Notes

BasicJsonType has no counterpart to this function: once a number is parsed into number_integer_t, number_unsigned_t, or number_float_t, its original textual form (leading zeros aside, which are already rejected by the grammar; trailing zeros in the fraction; the case and sign of the exponent; ...) is gone. number_token() is useful precisely where that form must survive — a price or an identifier that must be reproduced exactly, or a number too large for any of BasicJsonType's number types to hold without loss.

The returned string_view_t points into the document's source() text or, for a number written by an edit, into storage owned by the document (the token of an edited NaN is nan). It is valid exactly as long as that text or storage is, see the validity rules of basic_json_view. Numbers are never decoded into the document's separate string buffer.

For the same reason, the token must not be passed to read() of the document it came from if that document owns its text or the number was written by an edit: read() releases both before it parses.

Examples

??? example

The example below keeps a price and an order ID exactly as they were written in an incoming order, where
converting them with [`get<T>()`](get.md) would lose information: the price picks up floating-point rounding, and
the order ID — more digits than a 64-bit integer holds — can only be approximated as a `#!cpp double` once
`#!cpp materialize()`d.

```cpp
--8<-- "examples/basic_json_view__number_token.cpp"
```

Output:

```json
--8<-- "examples/basic_json_view__number_token.output"
```

See also

Version history

  • Added in version 3.13.0.