-
Notifications
You must be signed in to change notification settings - Fork 0
Decoding JSON
This page contains a detailed guide on how to parse a JSON string using the Arduino JSON library
Before writing any code, don't forget to include the header:
#include <ArduinoJson.h>
For instructions on how to install the library, please read [Using the library with Arduino](Using the library with Arduino) or [Using the library without Arduino](Using the library without Arduino).
Here an example that parse the string {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}:
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
//
// Step 1: Reserve memory space
//
StaticJsonBuffer<200> jsonBuffer;
//
// Step 2: Deserialize the JSON string
//
JsonObject& root = jsonBuffer.parseObject(json);
if (!root.success())
{
Serial.println("parseObject() failed");
return;
}
//
// Step 3: Retrieve the values
//
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the StaticJsonBuffer.
Before continuing please read the page [Arduino JSON memory model](Memory model) that explains everything you need to know about StaticJsonBuffer.
You invoke the JSON parser through the instance of StaticJsonBuffer.
It exposes two functions for parsing JSON:
-
parseArray()that returns a reference to aJsonArray -
parseObject()that returns a reference to aJsonObject
Let's see an example.
Say we want to parse {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}, it's an object so we call parseObject() as follows:
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
JsonObject& root = jsonBuffer.parseObject(json);
As you can see parseObject() takes a char* as a parameter.
Be careful, it's not a const char*, the memory must be writable.
Indeed, the parser will modify the string in two cases:
- to insert string endings (character
\0), - to translate escaped characters (like
\nor\t).
Another thing that you must keep in mind is that the string (char json[] in the example above) must stay in memory during the whole parsing process.
That is because the in memory object tree will store pointer to chunks of the string, so as to avoid any memory duplication.
Now, to check if the parsing was successful, you can call JsonObject::success():
if (!root.success())
{
// Parsing fail
}
The result can be false for three reasons:
- the JSON string is invalid,
- the JSON string doesn't represent an object,
- the
StaticJsonBufferis too small.
We just saw how to parse an object, there is nothing more to say for arrays, the procedure is exactly the same.
Now that the object or array is in memory, you can extract the data very easily.
In this section, we'll see how to do it with a JsonObject.
Once again, there is nothing more to say about arrays, JsonArray works exactly the same as JsonObject.
The simplest way is to use the subscript operator of JsonObject:
const char* sensor = root["sensor"];
long time = root["time"];
You can chain the subscript operator if you have nested arrays or objects:
double latitude = root["data"][0];
double longitude = root["data"][1];
But alternatively, you can get a reference to the nested array:
JsonArray& nestedArray = root["data"];
In the previous examples, the values were implicitly casted to the target type. You can also do this explicitly
const char* sensor = root["sensor"].asString();
long time = root["time"].as<long>();
JsonArray& nestedArray = root["data"].asArray();
If the actual value doesn't match the target type, a default value will be return:
-
falsefor boolean values -
0for integer values -
NULLfor string values -
JsonArray::invalid()for nested arrays -
JsonObject::invalid()for nested object
If you want to know if some value is present, call containsKey():
if (root.containsKey("extra"))
{
// root["extra"] is valid
}
If you want to check the type value has a certain type, call is<T>():
if (root["extra"].is<JsonArray&>())
{
// root["extra"] is an array
}
You can also iterate through the key-value pairs of the object:
for (JsonObject::iterator it=root.begin(); it!=root.end(); ++it)
{
Serial.println(it->key);
Serial.println(it->value.asString());
}
Let's take what we've learned above up a gear :)
Our JSON array is now:
char json[] = "{\"data\":{\"time\":{\"day\":1,\"month\":3,\"year\":16,\"hours\":9,\"mins\":59,\"secs\":14}}}";
We parse it and check it as before with:
JsonObject& root = jsonBuffer.parseObject(json);
// Test if parsing succeeds.
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
Now to get the data, we can follow the object downwards, just like you would do with PHP etc...:
int day = root["data"]["time"]["day"];
int month = root["data"]["time"]["month"];
int year = root["data"]["time"]["year"];
int hours = root["data"]["time"]["hours"];
int mins = root["data"]["time"]["mins"];
int secs = root["data"]["time"]["secs"];
This allows for more complex data to be processed, the time as in this example or numerous values from a single function. Just make sure your jsonBuffer is large enough to handle the larger objects!
See the file called "JsonParserExample_Advanced.ino" in "ArduinoJson/examples/JsonParserExample/"