deserializeMsgPack()
Description
deserializeMsgPack()
parses a MessagePack input and puts the result in a JsonDocument
.
Before reading the input, this function resets the document, so you don’t need to call JsonDocument::clear()
.
This function behaves differently depending on the type of input:
- For a read-only input, it duplicates the strings in the input document. This duplication consumes additional space in the
JsonDocument
. - For a writeable input, it stores pointers to the strings in the input buffer. This is the zero-copy mode. In this mode, the
JsonDocument
can be smaller, but ArduinoJson needs to modify the input buffer to insert null-terminators and replace escaped characters. Because theJsonDocument
stores pointers to the input buffer, you must ensure that this buffer remains in memory.
Prefer the first mode when the input comes from a Stream
; prefer the second when the input is in a buffer.
If the input is a char*
, ensure the input buffer stays in memory until the JsonDocument
is destructed.
Signatures
// writable input => zero-copy
DeserializationError deserializeMsgPack(JsonDocument& doc, char* input);
DeserializationError deserializeMsgPack(JsonDocument& doc, char* input, size_t inputSize);
// read-only input => duplication
DeserializationError deserializeMsgPack(JsonDocument& doc, const char* input);
DeserializationError deserializeMsgPack(JsonDocument& doc, const char* input, size_t inputSize);
DeserializationError deserializeMsgPack(JsonDocument& doc, const __FlashStringHelper* input);
DeserializationError deserializeMsgPack(JsonDocument& doc, const __FlashStringHelper* input, size_t inputSize);
DeserializationError deserializeMsgPack(JsonDocument& doc, const String& input); // 💀
DeserializationError deserializeMsgPack(JsonDocument& doc, const std::string& input);
DeserializationError deserializeMsgPack(JsonDocument& doc, Stream& input);
DeserializationError deserializeMsgPack(JsonDocument& doc, std::istream& input);
DeserializationError deserializeMsgPack(JsonDocument& doc, JsonVariantConst input);
template<typename Reader> // custom reader class (see below)
DeserializationError deserializeMsgPack(JsonDocument& doc, Reader& input);
// all overloads also accept optional parameters (see below)
Arduino’s String
doesn’t allow nulls inside the string; don’t use this class for MessagePack documents.
Support for JsonVariantConst
as input was added in ArduinoJson 6.15.2
Arguments
doc
: the JsonDocument
that will store the memory representation of the MessagePack document.
input
: the MessagePack document to parse:
const char*
is a string in RAMconst __FlashStringHelper*
is a Flash string, usually created withF()
Stream
is Arduino’s I/O stream interface, implemented by:HardwareSerial
(the class ofSerial
)SoftwareSerial
EthernetClient
WifiClient
WiFiClientSecure
BluetoothClient
EthernetUDP
GSMClient
File
TwoWire
(the class ofWire
)
inputSize
: the maximum number of bytes to read from input
This function supports two optional parameters:
- a parameter of type
DeserializationOption::NestingLimit
to change the maximum number of nesting levels that the parser will accept (see “Nesting Limit” below); - a parameter of type
DeserializationOption::Filter
to filter the input document and keep only the fields you need (see “Filtering” below).
Return value
deserializeMsgPack()
returns a DeserializationError
.
Configuration
deserializeMsgPack()
can be configured with the following settings:
ARDUINOJSON_DEFAULT_NESTING_LIMIT
sets the default nesting limit (see above),ARDUINOJSON_ENABLE_ARDUINO_STREAM
allows using aStream
as input.ARDUINOJSON_ENABLE_ARDUINO_STRING
allows using aString
as input (not recommended).ARDUINOJSON_ENABLE_INFINITY
allowsInfinity
in the input.ARDUINOJSON_ENABLE_NAN
allowsNaN
in the input,ARDUINOJSON_ENABLE_PROGMEM
allows using a Flash string as input.ARDUINOJSON_ENABLE_STD_STREAM
allows using astd::istream
as input.ARDUINOJSON_ENABLE_STD_STRING
allows using astd::string
as input.
Nesting limit
The ArduinoJson’s parser contains a recursive function that is called each time an object or an array begins. In other words, each object/array nesting level causes a recursive call. This recursive call is a security risk because an attacker could craft a JSON input with many opening brackets to cause a stack overflow.
To protect against this security risk, ArduinoJson limits the number of nesting levels. The macro ARDUINOJSON_DEFAULT_NESTING_LIMIT
sets the default value.
If your MessagePack input contains more nesting levels than allowed, you can pass an extra parameter of type DeserializationOption::NestingLimit
to deserializeMsgPack()
.
Filtering
When the input document contains many fields that are not relevant to your application, you can ask deserializeMsgPack()
to ignore them and save a lot of space in the JsonDocument
.
To use this feature, create an ancillary JsonDocument
that contains the value true
as a placeholder for every field you want to keep in the final document.
For arrays, only create one element in the filter document, it will serve as a filter for all elements of the original array.
Wrap this document in a DeserializationOption::Filter
before passing it to deserializeMsgPack()
.
See JsonFilterExample.ino for an example.
When filtering, deserializeMsgPack()
needs some extra room in the JsonDocument
to store object keys temporarily.
Make sure to increase the capacity a bit, or you may get a NoMemory
error.
This feature was added in ArduinoJson 6.17.0
Performance
When you pass a Stream
to deserializeMsgPack()
, it consumes bytes one by one, which can be slow depending on the input you use. For example, if you read from a SPIFFS file, you can read twenty times faster by reading chunks of 64 bytes.
To read the stream in chunks, you can use ReadBufferingStream
from the StreamUtils library.
Suppose your program is:
deserializeMsgPack(doc, file);
If you want to make deserializeMsgPack()
read chunks instead of reading bytes one by one, replace this line with:
ReadBufferingStream bufferingStream(file, 64);
deserializeMsgPack(doc, bufferingStream);
The first line creates a new Stream
that reads blocks of 64 bytes from file
.
Custom reader
If none of the supported input types is suitable for you, you can implement a custom reader class. This class must implement two member functions, as shown below:
struct CustomReader {
// Reads one byte, or returns -1
int read();
// Reads several bytes, returns the number of bytes read.
size_t readBytes(char* buffer, size_t length);
};
Then, pass a reference to an instance of this class as the second argument of deserializeMsgPack()
.
Example
char input[] = "\x81\xA5hello\xA5world";
StaticJsonDocument<200> doc;
deserializeMsgPack(doc, input);
const char* world = doc["hello"];