diff --git a/README.md b/README.md index 31e80e908..c63c512f4 100644 --- a/README.md +++ b/README.md @@ -1822,6 +1822,15 @@ The library itself consists of a single header file licensed under the MIT licen ## Notes +### Standards compliance + +The library targets strict conformance with [RFC 8259](https://tools.ietf.org/html/rfc8259.html). Both the original [JSONTestSuite](https://github.com/nst/JSONTestSuite) and its updated revision are exercised in CI; their test data is downloaded from [`nlohmann/json_test_data`](https://github.com/nlohmann/json_test_data) at configure time rather than committed to this repository (see [`tests/src/unit-testsuites.cpp`](https://github.com/nlohmann/json/blob/develop/tests/src/unit-testsuites.cpp)): + +- The updated revision runs all mandatory `y_` (must-accept) and `n_` (must-reject) cases through the strict [`parse()`](https://json.nlohmann.me/api/basic_json/parse/) entry point; the original suite runs its `n_` cases through `parse()` and its `y_` cases through [`operator>>`](https://json.nlohmann.me/api/operator_gtgt/). +- The `i_` (implementation-defined) cases are, by RFC 8259, free to be accepted *or* rejected, so "passing all `i_` cases" is not a meaningful conformance metric. The library makes deliberate, documented choices there: nesting depth is not artificially limited, a leading UTF-8 byte order mark is silently ignored, [Unicode noncharacters](https://www.unicode.org/faq/private_use.html#nonchar1) are forwarded unchanged, invalid UTF-8 and lone/unpaired UTF-16 surrogates are rejected (stricter than required), and a number that cannot be stored without becoming `NaN`/`INF` raises [`out_of_range.406`](https://json.nlohmann.me/home/exceptions/#jsonexceptionout_of_range406). + +One behavioral nuance is worth calling out, because a superficial test often misreads it as non-compliance: [`parse()`](https://json.nlohmann.me/api/basic_json/parse/) is strict and rejects trailing data after a value, whereas [`operator>>`](https://json.nlohmann.me/api/operator_gtgt/) follows relaxed iostream semantics — it parses a single value and leaves the stream positioned right after it. Feeding "a valid document followed by trailing bytes" through `operator>>` reports success; the same input through `parse()` is rejected. This is a documented two-API design, not a conformance gap. See [**parsing**](https://json.nlohmann.me/features/parsing/) for details. + ### Character encoding The library supports **Unicode input** as follows: diff --git a/docs/mkdocs/docs/features/parsing/index.md b/docs/mkdocs/docs/features/parsing/index.md index c3cb88f63..17624b8a2 100644 --- a/docs/mkdocs/docs/features/parsing/index.md +++ b/docs/mkdocs/docs/features/parsing/index.md @@ -28,6 +28,22 @@ Inputs consisting of multiple values separated by newlines are handled by the [J By default, the library rejects comments and trailing commas. Both can be enabled with parameters of the `parse` function — see [comments](../comments.md) and [trailing commas](../trailing_commas.md). +## Strictness and trailing data + +[`parse`](../../api/basic_json/parse.md) reads a single JSON value and requires the whole input to be consumed: any +non-whitespace data after the value is reported as a parse error. Use it when you want to guarantee that an input is +exactly one complete JSON document. + +[`operator>>`](../../api/operator_gtgt.md) follows relaxed `#!cpp std::istream` semantics instead: it parses one JSON +value and leaves the stream positioned right after it, without requiring the rest of the stream to be consumed. This is +what makes it possible to read several concatenated values from the same stream, but it also means that "a valid +document followed by trailing bytes" is accepted rather than rejected. If you are validating conformance, or need to +reject any input that is not exactly one JSON document, prefer `parse`. + +When using `operator>>` to read several concatenated values this way, a value that is a number must be followed by +whitespace, because `operator>>` consumes the character that terminates a number — see the +[`operator>>` notes](../../api/operator_gtgt.md#notes) for details and examples. + ## SAX vs. DOM parsing The library offers two parsing models: