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,0x00is ordinary data. - A bare
const char*pointer has no length of its own, so its length is still determined withstrlen(). 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 achararray (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¶
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:
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 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). 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.
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.
Workaround without the macro
To reject a NUL byte without enabling this macro, trim your input yourself before calling parse():
s.resize(s.find('\0')); // drop everything from the first NUL onward, if any
json::parse(s);
Examples¶
Default behavior (macro not defined)
Without the macro, a NUL byte silently ends parsing at that point:
#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
}
Opt-in strict handling (macro defined to 1)
With the macro, a NUL byte is rejected like any other unexpected byte:
#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¶
- FAQ: NUL bytes in the input
- parse - deserialize from a compatible input
- accept - check if the input is valid JSON
- operator>> - deserialize from stream
Version history¶
- Added in version 3.13.0.
- Planned to become the default (with the macro removed) in version 4.0.0.