Why parsing fails?
The parsing functions, parseArray()
and parseObject()
, may fail for 6 reasons:
- The input is not a valid JSON
- The
StaticJsonBuffer
is too small - The
StaticJsonBuffer
is too big (stack overflow) - The
DynamicJsonBuffer
fails to allocate memory - You called
parseObject()
instead ofparseArray()
- The nesting limit is too low
Case 1: The input is not a valid JSON
This seems obvious, but a lot of issues are caused by an invalid input.
In particular, if you’re writing an HTTP client, you need to
- Skip the HTTP headers.
- Use HTTP 1.0 to prevent chunked transfer encoding
- Increase the timeout
See JsonHttpClient.ino for a reference implementation.
Case 2: The StaticJsonBuffer
is too small
A JsonBuffer
is a memory pool where the JSON parser stores the tokens of the parsed object.
StaticJsonBuffer
is an implementation of a JsonBuffer
with fixed memory allocation.
This means that you need to specify the right size for the StaticJsonBuffer
, otherwise the parser will not be able to allocate the memory it needs, and therefore it will return an error.
Use ArduinoJson Assistant to compute the required size.
See also: How to reduce memory usage?
Case 3: The StaticJsonBuffer
is too big
A StaticJsonBuffer
is usually allocated on the stack, if it’s too big it will overlap with other variables. This usually leads to a crash or a reboot of the device.
If you are in this situation, you can either:
- Reduce the size of the
StaticJsonBuffer
, use ArduinoJson Assistant to compute the required size. - Switch to a
DynamicJsonBuffer
which is allocated on the heap.
For example, a ESP8266 has 4KB of stack memory. This means you only have 4096 bytes to store all your local variables, function parameters and calls return addresses. If the ArduinoJson Assistant says you need more than 1KB of RAM for the JsonBuffer
, then you should use a DynamicJsonBuffer
.
See also: How to reduce memory usage?
Case 4: The DynamicJsonBuffer
fails to allocate memory
Unlike the StaticJsonBuffer
which has a fixed size, the DynamicJsonBuffer
will automatically grow when full.
If the heap memory is exhausted, the DynamicJsonBuffer
will fail to allocate memory and the parsing will fail.
If you are in this situation:
- Make sure you have enough RAM, use ArduinoJson Assistant to compute the required size.
- Make sure you don’t reuse the same
JsonBuffer
. In particular make sure you don’t use a globalJsonBuffer
.
See also: How to reduce memory usage?
Case 5: You called parseObject()
instead of parseArray()
This is a very common question as people are often confused when the JSON input contains mixed arrays and objects.
The answer is very simple: it’s the type of the root that matters.
This means that you just need to look at the first character: it’s either a [
, for an array, or a {
, for an object.
For example, if the input is:
{"mickey":["mouse"],"donald":["duck"]}
then you must call parseObject()
because the root is an object.
And, if the input is:
[{"mickey":"mouse","donald":"duck"}]
then you must call parseArray()
because the root is an array.
Finally, if you cannot know in advance the type of the root, simply use JsonBuffer::parse()
which returns a JsonVariant
.
See also: Parsing succeeds but I can’t read the values!
Case 6: The nesting limit is too low
This can happen if you’re parsing an array or an object with many nesting levels, i.e. with a very deep layout.
You can solve this in two ways:
- You can pass an additional argument to
parseObject()
to specify the new limit. - You can define
ARDUINOJSON_DEFAULT_NESTING_LIMIT
which is the default for this argument
Where to go next?
The ArduinoJson ebook has a complete chapter on StaticJsonBuffer
and DynamicJsonBuffer
. Indeed, the most common source of error is related to the memory management; it is essential to understand what “stack,” “heap” and “global” memories are.
It contains new examples and explains how to apply the proper patterns and practices to your project. In particular, it shows how to prevent useless memory duplication, as it often causes parsing to fail.