Files
json/api/macros/json_strict_nul_handling.md
T
2026-09-24 07:41:05 +00:00

5.4 KiB

JSON_STRICT_NUL_HANDLING

#define JSON_STRICT_NUL_HANDLING /* value */

When defined to 1, a '\0' (NUL) byte in JSON text input is rejected with parse_error.101, like any other unexpected byte, instead of being silently treated as end of input.

The macro only affects the JSON text parser (parse, accept, sax_parse, and operator>>). There are three cases where a NUL byte is still not rejected:

  • The binary formats (from_bjdata, from_bson, from_cbor, from_msgpack, from_ubjson) are never affected: there, 0x00 is ordinary data.
  • A bare const char* pointer has no length of its own, so its length is still determined with strlen(). The first NUL byte therefore still marks the end of the input, and nothing after it is read.
  • One trailing '\0' at the end of a char array (e.g., a string literal) is trimmed; see the warning below.

Default definition

The default value is 0 (disabled — existing behavior is preserved).

#define JSON_STRICT_NUL_HANDLING 0

Notes

!!! note "Background"

By default, a `'\0'` byte anywhere in the input is treated the same as the real end of the input, rather than as
an ordinary (and, outside of a string, invalid) byte. Everything from that byte onward is silently ignored,
without a parse error - including further, otherwise well-formed JSON:

```cpp
json::parse(std::string("123") + '\0');          // == 123, no error
json::parse(std::string("123") + '\0' + "true"); // == 123, the "true" is silently ignored too
```

This falls out of the same convention used when no explicit input length is given at all: parsing from a
`const char*` already stops at the first NUL byte via `strlen()`, since a bare pointer has no length of its own.
The library applies that same NUL-terminated-C-string convention uniformly, rather than only when a length is
genuinely unavailable - so a `std::string`, iterator range, or container whose content happens to include a NUL
byte is affected the same way a raw `const char*` would be (see the
[FAQ entry](../../home/faq.md#nul-bytes-in-the-input) for a fuller explanation).

This was not fixed unconditionally, because doing so is backwards-incompatible for any caller who happens to
depend on the current behavior - even unknowingly, for instance because their input already contains trailing
padding they never noticed was being discarded (see [#5530](https://github.com/nlohmann/json/issues/5530)).
This macro instead offers an opt-in path to the corrected behavior ahead of version 4.0.0, where it is planned to
become the default.

!!! warning "Opt-in only"

This macro must be defined **before** including `<nlohmann/json.hpp>`. Defining it after the include has no
effect.

Enabling it also changes how a `char` array (including a string literal, e.g. `json::parse("123")`) is read: such
an array normally carries a trailing `'\0'` contributed by the compiler, not by the source text. With this macro
enabled, that one trailing byte is trimmed if present so that parsing a string literal keeps working; every other
byte in the array - including any `'\0'` that is not the very last element - is read as real data and rejected
like any other unexpected byte. Arrays of any other element type (`unsigned char`, `std::uint8_t`, ...), as used
for CBOR or MessagePack, are never affected by this trimming; their full extent - including a genuine trailing
`0x00` - is always preserved, in both states of this macro.

!!! tip "Workaround without the macro"

To reject a NUL byte without enabling this macro, trim your input yourself before calling `parse()`:

```cpp
s.resize(s.find('\0')); // drop everything from the first NUL onward, if any
json::parse(s);
```

Examples

??? example "Default behavior (macro not defined)"

Without the macro, a NUL byte silently ends parsing at that point:

```cpp
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    json j = json::parse(std::string("123") + '\0' + "true");
    // j is 123 -- the '\0' and everything after it is silently ignored
}
```

??? example "Opt-in strict handling (macro defined to 1)"

With the macro, a NUL byte is rejected like any other unexpected byte:

```cpp
#define JSON_STRICT_NUL_HANDLING 1
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    json j = json::parse(std::string("123") + '\0' + "true");
    // throws parse_error.101 -- the NUL byte is now invalid input,
    // exactly like any other unexpected trailing byte

    json ok = json::parse("123");
    // ok is 123 -- parsing from a string literal still works
}
```

See also

Version history

  • Added in version 3.13.0.
  • Planned to become the default (with the macro removed) in version 4.0.0.