* docs: document that a NUL byte in the input is treated as end of input A NUL byte anywhere in the input - trailing, or embedded ahead of more otherwise well-formed JSON - is currently treated the same as genuine end of input, so parsing silently stops there instead of raising the parse_error.101 any other unexpected byte triggers. This mirrors the NUL-terminated-C-string convention already used when no explicit input length is given (json::parse(const char*) already stops at strlen()), just applied uniformly rather than only when a length is genuinely unavailable. This behavior predates this change and is not being altered here - changing it would be an observable, backwards-incompatible behavior change for any caller that (knowingly or not) depends on it, which is not something to do silently in a patch. Documenting the current, verified behavior as a new FAQ entry instead, so it's an intentional and discoverable part of the contract rather than a surprise. Fixes #5530. Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com> Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4RQ1Ahan5YAGbnAQGjZTY * Add JSON_STRICT_NUL_HANDLING opt-in macro for issue #5530 A NUL byte anywhere in the input is currently treated the same as real end of input, rather than raising parse_error.101 like any other unexpected byte (documented in the previous commit's FAQ entry). A full unconditional fix was tried in PR #5532 but rejected as too risky to ship by default: any caller could depend on the current behavior, even unknowingly (e.g. a zero-padded buffer). On PR #5534, gregmarr proposed a compile-time opt-in flag instead, and the maintainer agreed, wanting it available now and defaulting to the corrected behavior in 4.0.0. This mirrors the existing JSON_BRACE_INIT_COPY_SEMANTICS precedent as closely as sensible: - JSON_STRICT_NUL_HANDLING defaults to 0 (off); the three lexer sites that treat '\0' as EOF/comment-terminator are gated with `#if !JSON_STRICT_NUL_HANDLING` so the default-off behavior is byte-for-byte identical to today's. - input_adapters.hpp's `T (&array)[N]` overload additionally trims a single trailing '\0' from a `char` array (e.g. a string literal like `json::parse("123")`) when the macro is on, so that case keeps working; every other element type (unsigned char, std::uint8_t, ...) always keeps its full extent. This intentionally does *not* reuse the existing strlen()-based pointer overload via SFINAE-excluding `char` from the array overload, as originally sketched for this change: that approach is ambiguous against the newer generic container overload added since PR #5532, and even where it compiles, strlen()-scanning a `char` array that is not NUL-terminated within its bounds reads past the end of the array (confirmed with AddressSanitizer). Trimming only a single trailing byte, without scanning, avoids both problems. - Documented via docs/mkdocs/docs/api/macros/json_strict_nul_handling.md, linked from the macros index/nav/features page, the FAQ entry, and the parse/accept/operator>> reference pages. - Tested in unit-class_parser.cpp and unit-deserialization.cpp, default state unguarded and opt-in state guarded. Since the library itself #undefs the macro at the end of json.hpp (as JSON_BRACE_INIT_COPY_SEMANTICS already does), a plain `#if defined(JSON_STRICT_NUL_HANDLING)` guard after the include never actually triggers; the tests instead capture the command-line value into a test-local macro before including the header. A few pre-existing fixtures elsewhere (std::array<uint8_t, N> sized one larger than their literal, relying on value-initialization to silently add a trailing zero byte) needed the same one-byte adjustment to keep passing under the opt-in behavior. Unlike the precedent, this adds a proper `JSON_StrictNulHandling` CMake option (rather than a raw -DCMAKE_CXX_FLAGS injection) and wires its ci_test_strict_nul_handling target into the ci_cmake_options job matrix in .github/workflows/ubuntu.yml, so the opt-in build is actually exercised in CI -- closing the one gap in the precedent's own CI setup (ci_test_brace_init_copy_semantics is defined but never referenced by any workflow, so it has never actually run). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Clarify where JSON_STRICT_NUL_HANDLING does not reject NUL bytes Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <niels.lohmann@gmail.com> Signed-off-by: Niels Lohmann <mail@nlohmann.me> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
140 lines
5.3 KiB
Markdown
140 lines
5.3 KiB
Markdown
# <small>nlohmann::basic_json::</small>accept
|
|
|
|
```cpp
|
|
// (1)
|
|
template<typename InputType>
|
|
static bool accept(InputType&& i,
|
|
const bool ignore_comments = false,
|
|
const bool ignore_trailing_commas = false);
|
|
|
|
// (2)
|
|
template<typename IteratorType, typename SentinelType = IteratorType>
|
|
static bool accept(IteratorType first, SentinelType last,
|
|
const bool ignore_comments = false,
|
|
const bool ignore_trailing_commas = false);
|
|
```
|
|
|
|
Checks whether the input is valid JSON.
|
|
|
|
1. Reads from a compatible input.
|
|
2. Reads from a pair of character iterators, or an iterator and a sentinel of a different type (C++20 ranges support)
|
|
|
|
The value_type of the iterator must be an integral type with a size of 1, 2, or 4 bytes, which will be interpreted
|
|
respectively as UTF-8, UTF-16, and UTF-32. If `SentinelType` differs from `IteratorType`, it must be comparable to
|
|
the iterator type with `operator!=`.
|
|
|
|
Unlike the [`parse()`](parse.md) function, this function neither throws an exception in case of invalid JSON input
|
|
(i.e., a parse error) nor creates diagnostic information.
|
|
|
|
## Template parameters
|
|
|
|
`InputType`
|
|
: A compatible input, for instance:
|
|
|
|
- an `std::istream` object
|
|
- a `#!c FILE` pointer (throws if null)
|
|
- a C-style array of characters
|
|
- a pointer to a null-terminated string of single byte characters (throws if null)
|
|
- a `std::string`
|
|
- a container `obj` for which `begin(obj)` and `end(obj)` produce a valid pair of iterators
|
|
(as found via ADL or member functions, with semantics compatible to `std::begin` and `std::end`)
|
|
|
|
`IteratorType`
|
|
: a compatible iterator type, for instance.
|
|
|
|
- a pair of `std::string::iterator` or `std::vector<std::uint8_t>::iterator`
|
|
- a pair of pointers such as `ptr` and `ptr + len`
|
|
|
|
`SentinelType`
|
|
: defaults to `IteratorType`; may be a different type comparable to `IteratorType` via `operator!=`, for instance.
|
|
|
|
- a custom sentinel type for C++20 ranges
|
|
- `std::default_sentinel_t`, when `IteratorType` is `std::counted_iterator`
|
|
|
|
## Parameters
|
|
|
|
`i` (in)
|
|
: Input to parse from.
|
|
|
|
`ignore_comments` (in)
|
|
: whether comments should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
|
|
(`#!cpp false`); (optional, `#!cpp false` by default)
|
|
|
|
`ignore_trailing_commas` (in)
|
|
: whether trailing commas in arrays or objects should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
|
|
(`#!cpp false`); (optional, `#!cpp false` by default)
|
|
|
|
`first` (in)
|
|
: iterator to the start of the character range
|
|
|
|
`last` (in)
|
|
: iterator to the end of the character range, or a sentinel value that compares equal to the end iterator with `operator!=`
|
|
|
|
## Return value
|
|
|
|
Whether the input is valid JSON.
|
|
|
|
## Exception safety
|
|
|
|
Strong guarantee: if an exception is thrown, there are no changes in the JSON value.
|
|
|
|
## Exceptions
|
|
|
|
Throws [`parse_error.101`](../../home/exceptions.md#jsonexceptionparse_error101) in case of an empty input like a null `#!c FILE*` or `#!c char*` pointer.
|
|
|
|
## Complexity
|
|
|
|
Linear in the length of the input. The parser is a predictive LL(1) parser.
|
|
|
|
## Notes
|
|
|
|
A UTF-8 byte order mark is silently ignored.
|
|
|
|
By default, a `'\0'` (NUL) byte anywhere in the input is treated as end of input, rather than as an ordinary (and,
|
|
outside of a string, invalid) byte; see the [FAQ entry](../../home/faq.md#nul-bytes-in-the-input) for details and the
|
|
[`JSON_STRICT_NUL_HANDLING`](../macros/json_strict_nul_handling.md) macro to opt into rejecting it instead.
|
|
|
|
## Examples
|
|
|
|
??? example
|
|
|
|
The example below demonstrates the `accept()` function reading from a string.
|
|
|
|
```cpp
|
|
--8<-- "examples/accept__string.cpp"
|
|
```
|
|
|
|
Output:
|
|
|
|
```json
|
|
--8<-- "examples/accept__string.output"
|
|
```
|
|
|
|
## See also
|
|
|
|
- [parse](parse.md) - deserialize from a compatible input
|
|
- [sax_parse](sax_parse.md) - parse input using the SAX interface
|
|
- [operator>>](../operator_gtgt.md) - deserialize from stream
|
|
- [`JSON_STRICT_NUL_HANDLING`](../macros/json_strict_nul_handling.md) - opt in to rejecting a NUL byte in the input
|
|
instead of treating it as end of input
|
|
|
|
## Version history
|
|
|
|
- Added in version 3.0.0.
|
|
- Ignoring comments via `ignore_comments` added in version 3.9.0.
|
|
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
|
|
- Added `ignore_trailing_commas` in version 3.13.0.
|
|
- Extended container support (1) to include types with lvalue-only ADL `begin`/`end` (matching `std::begin`/`std::end` semantics) in version 3.13.0.
|
|
- Extended overload (2) to accept heterogeneous iterator+sentinel pairs (C++20 ranges support) in version 3.13.0.
|
|
- `JSON_STRICT_NUL_HANDLING` added in version 3.13.0 to optionally reject a NUL byte in the input instead of treating
|
|
it as end of input; planned to become the default in version 4.0.0.
|
|
|
|
!!! warning "Deprecation"
|
|
|
|
Overload (2) replaces calls to `accept` with a pair of iterators as their first parameter which has been
|
|
deprecated in version 3.8.0. This overload will be removed in version 4.0.0. Please replace all calls like
|
|
`#!cpp accept({ptr, ptr+len}, ...);` with `#!cpp accept(ptr, ptr+len, ...);`.
|
|
|
|
You should be warned by your compiler with a `-Wdeprecated-declarations` warning if you are using a deprecated
|
|
function.
|