Why is the input modified?
The JSON parser works in two different modes, depending on whether the input is read-only or not.
Mode 1: read-only input
ArduinoJson uses the “read-only” mode when you pass one of the following types to deserializeJson():
const char*std::stringstd::istreamStringStreamconst __FlashStringHelper*
In this mode, the parser copies relevant pieces of the input in the JsonDocument.
Examples:
const char* json = "{\"hello\":\"world\"}";
deserializeJson(doc, json);
String json = "{\"hello\":\"world\"}";
deserializeJson(doc, json);
Mode 2: zero-copy
ArduinoJson uses the “zero-copy” mode when you pass one of the following types to deserializeJson():
char*char[]
In this mode, the JSON parser modifies the input in place. The following modifications are performed:
'\0'are inserted at the end of each string- Escaped special characters (like
\n) are unescaped
Example:
char[] json = "{\"hello\":\"world\"}";
deserializeJson(doc, json);
After executing the line above, the input variable probably contains something like "hello\0world\0".
Calling deserializeJson() twice
Because the input buffer is altered, if you call deserializeJson() twice, the second call will return InvalidInput, as in the example below:
char[] json = "{\"hello\":\"world\"}";
deserializeJson(doc, json); // Ok
deserializeJson(doc, json); // InvalidInput
Switching to classic mode
Usually, the “zero-copy” mode is what you want because it reduces memory usage. However, if you need to switch back to the “classic” mode, you can cast the input pointer to const char*, like so:
char[] json = "{\"hello\":\"world\"}";
deserializeJson(doc, (const char*)json); // cast to avoid "zero-copy" mode
See also
- Deserialization Tutorial
- Chapter “Inside ArduinoJson” of Mastering ArduinoJson