mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-08-09 15:44:42 +02:00
Moved user manual to https://bblanchon.github.io/ArduinoJson/doc/
@@ -1 +1 @@
|
||||
🚚 The API Reference has been moved to https://bblanchon.github.io/ArduinoJson/api/ 🚚
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/api/ 🚚
|
||||
|
@@ -1,143 +1 @@
|
||||
As `StaticJsonBuffer` is the corner stone of this library, you'll see that every pitfall listed here is related to a wrong understanding of the memory model.
|
||||
|
||||
Make sure you read [Arduino JSON memory model](Memory model) before going further.
|
||||
|
||||
#### 1. Make `StaticJsonBuffer` big enough
|
||||
|
||||
By design, the library has no way to tell you why `parseArray()` or `parseObject()` failed.
|
||||
|
||||
There are basically two reasons why they may fail:
|
||||
|
||||
1. the JSON string is invalid,
|
||||
2. the JSON string contains more values that the buffer can store.
|
||||
|
||||
So, if you are sure the JSON string is correct and you still can't parse it, you should try to increase the size of the `StaticJsonBuffer`.
|
||||
|
||||
You can use the [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/) to compute the required size.
|
||||
|
||||
#### 2. Make sure everything fits in memory
|
||||
|
||||
You may go into unpredictable trouble if you allocate more memory than your processor really has.
|
||||
It's a very common issue in embedded development.
|
||||
|
||||
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
|
||||
|
||||
For example, don't do this:
|
||||
|
||||
char json[1024]; // 1 KB
|
||||
StaticJsonBuffer<512> buffer; // 514 B
|
||||
|
||||
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
|
||||
|
||||
That is why an 8-bit processor is not able to parse long and complex JSON strings.
|
||||
|
||||
#### 3. Keep the `StaticJsonBuffer` in memory long enough
|
||||
|
||||
Remember that `StaticJsonBuffer`'s function return references.
|
||||
References don't contain data, they are just pointer to the actual.
|
||||
So they can only work if the actual data is in memory.
|
||||
|
||||
For example, don't do this:
|
||||
|
||||
JsonArray& getArray(char* json)
|
||||
{
|
||||
StaticJsonBuffer<200> buffer;
|
||||
return buffer.parseArray(json);
|
||||
}
|
||||
|
||||
because the local variable `buffer` will be *removed* from memory when the function `parseArray()` returns, and the `JsonArray&` will point to an invalid location.
|
||||
|
||||
#### 4. Don't reuse the same `JsonBuffer`
|
||||
|
||||
During is lifetime a `JsonBuffer` growth until it's discarded. If you try to reuse the same instance several time, it will rapidly get full. This is true for both `DynamicJsonBuffer` and `StaticJsonBuffer`.
|
||||
|
||||
For this reason, **you should not use a global variable** for your `JsonBuffer`. I don't think there is any scenario in which a global `JsonBuffer` would be a valid option.
|
||||
|
||||
The best practice is to **declare it in a local scope**, so that it's discarded as soon as possible. My advice is to declare it in a function whose unique role is to handle the JSON serialization.
|
||||
|
||||
See [FAQ: The first parsing succeeds, why does the next ones fail?](https://bblanchon.github.io/ArduinoJson/faq/the-first-parsing-succeeds-why-do-the-next-ones-fail)
|
||||
|
||||
#### 5. Keep the JSON string in memory long enough
|
||||
|
||||
The library never make memory duplication.
|
||||
This has an important implication on string values, it means that the library will return pointer to chunks of the string.
|
||||
|
||||
For instance, let's imagine that you parse `["hello","world"]`, like this:
|
||||
|
||||
char[] json = "[\"hello\",\"world\"]";
|
||||
StaticJsonBuffer<32> buffer;
|
||||
JsonArray& array = buffer.parseArray(json);
|
||||
|
||||
const char* first = array[0];
|
||||
const char* second = array[1];
|
||||
|
||||
In that case, both `first` and `second` are pointers to the content of the original string `json`.
|
||||
So this will only work if `json` is still in memory.
|
||||
|
||||
#### 6. Do not assume that strings are copied
|
||||
|
||||
By default, ArduinoJson doesn't make copies of strings.
|
||||
This allows it to work with full static memory allocation and ensure an efficient use of CPU cycles.
|
||||
|
||||
But this can have subtle consequences...
|
||||
|
||||
For instance the following code will not work as expected:
|
||||
|
||||
JsonArray& array = jsonBuffer.createArray();
|
||||
for (int i=0; i<3; i++) {
|
||||
char buffer[16];
|
||||
sprintf(buffer, "iteration %d", i);
|
||||
array.add(buffer);
|
||||
}
|
||||
array.printTo(Serial);
|
||||
|
||||
One will probably expect the following result:
|
||||
|
||||
["iteration 0","iteration 1","iteration 2"]
|
||||
|
||||
but the actual result would be:
|
||||
|
||||
["iteration 2","iteration 2","iteration 2"]
|
||||
|
||||
because the same memory area has been reuse for each iteration.
|
||||
|
||||
The simplest solution is to explicitly duplicate the strings in the `JsonBuffer`:
|
||||
|
||||
JsonArray& array = jsonBuffer.createArray();
|
||||
for (int i=0; i<3; i++) {
|
||||
char buffer[16];
|
||||
sprintf(buffer, "iteration %d", 0);
|
||||
array.add(jsonBuffer.strdup(buffer));
|
||||
}
|
||||
array.printTo(Serial);
|
||||
|
||||
The same principle applies to key and values of `JsonObject`.
|
||||
|
||||
Note: If you use `String` instead of a `const char*`, ArduinoJson calls `JsonBuffer::strdup()` implicitly.
|
||||
|
||||
#### 7. Make sure the string isn't read-only
|
||||
|
||||
If you read carefully the previous section, you may have come to the conclusion that the JSON parser modifies the JSON string.
|
||||
|
||||
Indeed, the parser modifies the string for two reasons:
|
||||
|
||||
1. it inserts `\0` to terminate substrings,
|
||||
2. it translate escaped characters like `\n` or `\t`.
|
||||
|
||||
Most of the time this wont be an issue, but there are some corner cases that can be problematic.
|
||||
|
||||
Let take the example bellow:
|
||||
|
||||
char[] json = "[\"hello\",\"world\"]";
|
||||
StaticJsonBuffer<32> buffer;
|
||||
JsonArray& array = buffer.parseArray(json);
|
||||
|
||||
If you replace it by:
|
||||
|
||||
char* json = "[\"hello\",\"world\"]";
|
||||
StaticJsonBuffer<32> buffer;
|
||||
JsonArray& array = buffer.parseArray(json);
|
||||
|
||||
Depending on your platform, you may have an exception because the parser tries to write at a location that is read-only.
|
||||
In the first case `char json[]` declares an array of `char` initialized to the specified string.
|
||||
In the second case `char* json` declares a pointer to a read-only string, in fact it should be a `const char*` instead of a `char*`.
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/doc/pitfalls/ 🚚
|
||||
|
@@ -1,122 +1 @@
|
||||
<!-- MarkdownTOC depth=3 autolink=true bracket=round lowercase_only_ascii=true -->
|
||||
|
||||
- [Arduino Library Manager doesn't list the latest versions of ArduinoJson](#arduino-library-manager-doesnt-list-the-latest-versions-of-arduinojson)
|
||||
- [CodeBender](#codebender)
|
||||
- [Arduino Zero, mkr1000 and all boards based on SAMD21](#arduino-zero-mkr1000-and-all-boards-based-on-samd21)
|
||||
- [Warning: ignoring packed attribute because of unpacked non-POD field](#warning-ignoring-packed-attribute-because-of-unpacked-non-pod-field)
|
||||
- [Error: undefined reference to `__cxa_guard_acquire` and `__cxa_guard_release`](#error-undefined-reference-to-cxaguardacquire-and-cxaguardrelease)
|
||||
- [Adafruit WICED](#adafruit-wiced)
|
||||
- [ESP32](#esp32)
|
||||
- [Sloeber Arduino Eclipse Plugin](#sloeber-arduino-eclipse-plugin)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
|
||||
Despite the effort on writing portable code, there are compatibility issues with a few platform.
|
||||
|
||||
## Arduino Library Manager doesn't list the latest versions of ArduinoJson
|
||||
|
||||
This is a very common issue.
|
||||
If ArduinoJson doesn't appear in Libray Manager, or if only old versions are listed, try to delete the local cache.
|
||||
This will force the Libray Manager to download the library list from scratch.
|
||||
|
||||
For example, on Windows, you need to delete:
|
||||
|
||||
* `%LOCALAPPDATA%\Arduino15\library_index.json`
|
||||
* `%LOCALAPPDATA%\Arduino15\library_index.json.tmp.gz`
|
||||
|
||||
You don't even need to close Arduino, just re-open the library manager.
|
||||
|
||||
## CodeBender
|
||||
|
||||
For some reason, it's not possible to use ArduinoJson with CodeBender.
|
||||
|
||||
See discussion here: http://feedback.codebender.cc/forums/280538-library-requests/suggestions/7238254-arduinojson-support
|
||||
|
||||
## Arduino Zero, mkr1000 and all boards based on SAMD21
|
||||
|
||||
There is a bug in [Arduino SAMD core](https://github.com/arduino/ArduinoCore-samd) that make `prettyPrintTo()` fail (issue [#327](https://github.com/bblanchon/ArduinoJson/issues/327))
|
||||
|
||||
It's been fixed on May 27th by [arduino/ArduinoCore-samd@8ef9bb3](https://github.com/arduino/ArduinoCore-samd/commit/8ef9bb3d7bd026b57a8568030d8992644c9b8de8) and [arduino/ArduinoCore-samd@8d0c167](https://github.com/arduino/ArduinoCore-samd/commit/8d0c1674628df1c2c7592f4fc17467c694f5a1be).
|
||||
Unfortunately, version 1.6.6 only includes modifications up to May 19th, so the fix is not available through the Arduino Boards Manager.
|
||||
|
||||
I recommend to apply the modification manually or wait until the next release of the Arduino SAMD Core.
|
||||
The files to change are [`USBCore.cpp`](https://github.com/arduino/ArduinoCore-samd/commit/8ef9bb3d7bd026b57a8568030d8992644c9b8de8) and [`CDC.cpp`](https://github.com/arduino/ArduinoCore-samd/commit/8d0c1674628df1c2c7592f4fc17467c694f5a1be).
|
||||
|
||||
They are located here on Windows:
|
||||
|
||||
```
|
||||
%LOCALAPPDATA%\Arduino15\packages\arduino\hardware\samd\1.6.6\cores\arduino\USB
|
||||
```
|
||||
|
||||
## Warning: ignoring packed attribute because of unpacked non-POD field
|
||||
|
||||
If you pass the flag `--fpack-struct` to the compiler, it will generate the following warning:
|
||||
|
||||
```
|
||||
warning: ignoring packed attribute because of unpacked non-POD field
|
||||
```
|
||||
|
||||
No solution has been found so far: you need to remove that flag if you want to get rid of that warning.
|
||||
|
||||
See issue [#255](https://github.com/bblanchon/ArduinoJson/issues/255)
|
||||
|
||||
## Error: undefined reference to `__cxa_guard_acquire` and `__cxa_guard_release`
|
||||
|
||||
You need to add the following flag:
|
||||
|
||||
> `-fno-threadsafe-statics`
|
||||
> Do not emit the extra code to use the routines specified in the C++ ABI for thread-safe initialization of local statics. You can use this option to reduce code size slightly in code that doesn't need to be thread-safe.
|
||||
|
||||
See issue [#356](https://github.com/bblanchon/ArduinoJson/issues/356) and [#389](https://github.com/bblanchon/ArduinoJson/issues/389)
|
||||
|
||||
|
||||
## Adafruit WICED
|
||||
|
||||
There is currently a bug in the Arduino Core for Adafruit WICED Feather causing the following error:
|
||||
|
||||
```
|
||||
error: cannot convert 'err_t' to 'err_t (*)()
|
||||
```
|
||||
|
||||
See issue [#404](https://github.com/bblanchon/ArduinoJson/issues/404)
|
||||
|
||||
## ESP32
|
||||
|
||||
There is currently a bug in the [Arduino Core for ESP32](https://github.com/espressif/arduino-esp32) causing the following error:
|
||||
|
||||
```
|
||||
error: redefinition of 'struct ArduinoJson::Internals::StringFuncs<const char*>'
|
||||
```
|
||||
|
||||
The solution is to disable `PROGMEM` support in ArduinoJson.
|
||||
To do that, just add the following line at the top of your program:
|
||||
|
||||
```c++
|
||||
#define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||
```
|
||||
|
||||
Then, you may have the following linker error:
|
||||
|
||||
```
|
||||
undefined reference to__cxa_guard_release'
|
||||
```
|
||||
|
||||
To solve this, you need to add `-fno-threadsafe-statics` in `platform.txt`.
|
||||
|
||||
See issue [#407](https://github.com/bblanchon/ArduinoJson/issues/407)
|
||||
|
||||
|
||||
## Sloeber Arduino Eclipse Plugin
|
||||
|
||||
When compiling ArduinoJson within the Sloeber Arduino Eclipse Plugin, you may encounter the following error:
|
||||
|
||||
```
|
||||
C:/Utilities/sloeber/arduinoPlugin/libraries/ArduinoJson/5.8.2/fuzzing/fuzzer.cpp:3:39: error: expected class-name before '{' token class memstream : public std::istream
|
||||
```
|
||||
|
||||
You need to add the `fuzzin/` folder to the "Source Folder Exclusion Patterns", like on the pricture bellow:
|
||||
|
||||

|
||||
|
||||
See issues [ArduinoJson #432](https://github.com/bblanchon/ArduinoJson/issues/432) and [Sloeber #642](https://github.com/Sloeber/arduino-eclipse-plugin/issues/642).
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/faq/compilation-fails-device-crashes-nothing-on-serial-console/ 🚚
|
||||
|
185
Decoding-JSON.md
185
Decoding-JSON.md
@@ -1,184 +1 @@
|
||||
> *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).
|
||||
|
||||
## Example
|
||||
|
||||
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];
|
||||
|
||||
## Step 1: Reserve memory space
|
||||
|
||||
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`.
|
||||
|
||||
## Step 2: Parse the JSON string
|
||||
|
||||
You invoke the JSON parser through the instance of `StaticJsonBuffer`.
|
||||
It exposes two functions for parsing JSON:
|
||||
|
||||
1. `parseArray()` that returns a reference to a `JsonArray`
|
||||
2. `parseObject()` that returns a reference to a `JsonObject`
|
||||
|
||||
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:
|
||||
|
||||
1. to insert string endings (character `\0`),
|
||||
2. to translate escaped characters (like `\n` or `\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:
|
||||
|
||||
1. the JSON string is invalid,
|
||||
2. the JSON string doesn't represent an object,
|
||||
3. the `StaticJsonBuffer` is too small.
|
||||
|
||||
We just saw how to parse an object, there is nothing more to say for arrays, the procedure is exactly the same.
|
||||
|
||||
## Step 3: Retrieve the values
|
||||
|
||||
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`.
|
||||
|
||||
#### Subscript operator
|
||||
|
||||
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"];
|
||||
|
||||
#### Casting values
|
||||
|
||||
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:
|
||||
|
||||
1. `false` for boolean values
|
||||
2. `0` for integer values
|
||||
3. `NULL` for string values
|
||||
4. `JsonArray::invalid()` for nested arrays
|
||||
5. `JsonObject::invalid()` for nested object
|
||||
|
||||
#### Check values
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
Or if you want to iterate through a nested array:
|
||||
|
||||
JsonObject& data = variables["data"];
|
||||
for (auto dataobj : data){
|
||||
Serial.println(dataobj.key);
|
||||
}
|
||||
|
||||
## Advanced Example
|
||||
|
||||
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/"
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/doc/decoding/ 🚚
|
||||
|
186
Encoding-JSON.md
186
Encoding-JSON.md
@@ -1,185 +1 @@
|
||||
> *This page contains a detailed guide on how to generate a JSON string using the Arduino JSON library*
|
||||
|
||||
Before writing any code, don't forget to include the header:
|
||||
|
||||
```c++
|
||||
#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).
|
||||
|
||||
## Example
|
||||
|
||||
Here is an example to generate `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`
|
||||
|
||||
```c++
|
||||
//
|
||||
// Step 1: Reserve memory space
|
||||
//
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
//
|
||||
// Step 2: Build object tree in memory
|
||||
//
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||
|
||||
//
|
||||
// Step 3: Generate the JSON string
|
||||
//
|
||||
root.printTo(Serial);
|
||||
```
|
||||
|
||||
## Step 1: Reserve memory space
|
||||
|
||||
Arduino JSON uses a preallocated memory pool to store the object tree; this is done by the `StaticJsonBuffer`.
|
||||
|
||||
In the case of a `StaticJsonBuffer`, the memory is reserved on the stack. The template parameter (`200` in the example) is the number of bytes to reserved.
|
||||
|
||||
Alternatively, you can use a `DynamicJsonBuffer` that allocates memory on the heap and grow as required. It is the preferred way for devices with a significant amount of RAM, like the ESP8266.
|
||||
|
||||
See also:
|
||||
|
||||
* [Arduino JSON memory model](Memory model)
|
||||
* [FAQ: What are the differences between StaticJsonBuffer and DynamicJsonBuffer?](FAQ#what-are-the-differences-between-staticjsonbuffer-and-dynamicjsonbuffer)
|
||||
* [FAQ: How to determine the buffer size?](FAQ#how-to-determine-the-buffer-size)
|
||||
|
||||
## Step 2: Build object tree in memory
|
||||
|
||||
Once the `JsonBuffer` is ready, you can use it to build your in-memory representation of the JSON string.
|
||||
|
||||
#### Arrays
|
||||
|
||||
You create an array like this:
|
||||
|
||||
```c++
|
||||
JsonArray& array = jsonBuffer.createArray();
|
||||
```
|
||||
|
||||
Don't forget the `&` after `JsonArray`; it needs to be a reference to the array.
|
||||
|
||||
Then you can add strings, integer, booleans, etc:
|
||||
|
||||
```c++
|
||||
array.add("bazinga!");
|
||||
array.add(42);
|
||||
array.add(true);
|
||||
```
|
||||
|
||||
There are 3 syntaxes for floating point values:
|
||||
|
||||
```c++
|
||||
array.add(3.1415); // default: 2 digits -> "3.14"
|
||||
array.add(double_with_n_digits(3.1415, 4)); // explicit: 4 digits -> "3.1415"
|
||||
array.add(3.1415, 4); // same as previous -> "3.1415"
|
||||
```
|
||||
|
||||
> ##### About floating point precision
|
||||
> The overload of `add()` with 2 parameters allows you to specify the number of decimals to save in the JSON string.
|
||||
> When you use the overload with one parameter, you use the default number of decimals which is 2.
|
||||
> Note that this behavior is the same as Arduino's `Print::print(double,int)` which is implemented by `Serial`, so you may already be familiar with this behavior.
|
||||
|
||||
You can add a nested array or object if you have a reference to it.
|
||||
Or simpler, you can create nested array or nested objects from the array:
|
||||
|
||||
```c++
|
||||
JsonArray& nestedArray = array.createNestedArray();
|
||||
JsonObject& nestedObject = array.createNestedObject();
|
||||
```
|
||||
|
||||
#### Objects
|
||||
|
||||
You create an object like this:
|
||||
|
||||
```c++
|
||||
JsonObject& object = jsonBuffer.createObject();
|
||||
```
|
||||
|
||||
Again, don't forget the `&` after `JsonObject`, it needs to be a reference to the object.
|
||||
|
||||
Then you can add strings, integer, booleans, etc:
|
||||
|
||||
```c++
|
||||
object["key1"] = "bazinga!";
|
||||
object["key2"] = 42;
|
||||
object["key3"] = true;
|
||||
```
|
||||
|
||||
As for the arrays, there are two syntaxes for the floating point values:
|
||||
|
||||
```c++
|
||||
object["key4"] = double_with_n_digits(3.1415, 4); // 4 digits "3.1415"
|
||||
object["key5"] = 3.1415; // default: 2 digits "3.14"
|
||||
```
|
||||
|
||||
You can add a nested array or object if you have a reference to it.
|
||||
Or simpler, you can create nested array or nested objects from the object:
|
||||
|
||||
```c++
|
||||
JsonArray& nestedArray = object.createNestedArray("key6");
|
||||
JsonObject& nestedObject = object.createNestedObject("key7");
|
||||
```
|
||||
|
||||
> ##### Other JsonObject functions
|
||||
> * `object.set(key, value)` is a synonym for `object[key] = value`
|
||||
> * `object.set(key, value, digits)` is a synonym for `object[key] = double_with_n_digits(value, digits)`
|
||||
> * `object.containsKey(key)` returns `true` is the `key` is present in `object`
|
||||
> * `object.remove(key)` removes the `value` associated with `key`
|
||||
|
||||
## Step 3: Generate the JSON string
|
||||
|
||||
There are two ways tho get the resulting JSON string.
|
||||
|
||||
Depending on your project, you may need to dump the string in a classic `char[]` or send it to a `Print` implementation like `Serial` or `EthernetClient`.
|
||||
|
||||
Both ways are the easy way :-)
|
||||
|
||||
#### Use a classic `char[]`
|
||||
|
||||
Whether you have a `JsonArray&` or a `JsonObject&`, simply call `printTo()` with the destination buffer, like so:
|
||||
|
||||
```c++
|
||||
char buffer[256];
|
||||
array.printTo(buffer, sizeof(buffer));
|
||||
```
|
||||
|
||||
> ##### Want an indented output?
|
||||
> By default the generated JSON is as small as possible. It contains no extra space, nor line break.
|
||||
> But if you want an indented, more readable output, you can.
|
||||
> Simply call `prettyPrintTo` instead of `printTo()`:
|
||||
>
|
||||
> array.prettyPrintTo(buffer, sizeof(buffer));
|
||||
|
||||
#### Send to a `Print` implementation
|
||||
|
||||
It is very likely that the generated JSON ends up in a stream like `Serial` or `EthernetClient `, so you can save some time and memory by doing this:
|
||||
|
||||
```c++
|
||||
array.printTo(Serial);
|
||||
```
|
||||
|
||||
And, of course if you need an indented JSON string:
|
||||
|
||||
```c++
|
||||
array.prettyPrintTo(Serial);
|
||||
```
|
||||
|
||||
> ##### About the Print interface
|
||||
> The library is designed to send the JSON string to an implementation of the `Print` interface that is part of Arduino.
|
||||
> In the example above we used `Serial`, but they are many other implementations that would work as well, including: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`, `Wire`...
|
||||
> When you use this library out of the Arduino environment, it uses its own implementation of `Print` and everything is the same.
|
||||
|
||||
#### Length of the output data
|
||||
|
||||
If you need to know the length of the output data beforehand, use the `measureLength()` method:
|
||||
|
||||
```c++
|
||||
int len = array.measureLength();
|
||||
```
|
||||
|
||||
That comes in handy when you need to calculate the `Content-Length` when posting JSON data over HTTP.
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/doc/encoding/ 🚚
|
||||
|
28
Home.md
28
Home.md
@@ -1,19 +1,19 @@
|
||||
#### Installation
|
||||
- [Using the library with Arduino](Using the library with Arduino)
|
||||
- [Using the library without Arduino](Using the library without Arduino)
|
||||
- [Using the library in a CMake project](Using the library in a CMake project)
|
||||
- [Quick start](Quick Start)
|
||||
|
||||
#### User guide
|
||||
- [Quick start](Quick Start)
|
||||
- [Memory model](Memory model)
|
||||
- [Decoding JSON](Decoding JSON)
|
||||
- [Encoding JSON](Encoding JSON)
|
||||
- [Examples](Examples)
|
||||
- [Avoiding pitfalls](Avoiding pitfalls)
|
||||
- ~~[Migrating code to new the API](Migrating code to the new API)~~ (obsolete)
|
||||
- [Compatibility issues](Compatibility issues)
|
||||
- [F.A.Q (Frequently Asked Questions) :confused:](https://bblanchon.github.io/ArduinoJson/faq/)
|
||||
|
||||
- [Installation](https://bblanchon.github.io/ArduinoJson/doc/installation/)
|
||||
- [Decoding JSON](https://bblanchon.github.io/ArduinoJson/doc/decoding/)
|
||||
- [Encoding JSON](https://bblanchon.github.io/ArduinoJson/doc/encoding/)
|
||||
- [Memory model](https://bblanchon.github.io/ArduinoJson/doc/memory/)
|
||||
- [Avoiding pitfalls](https://bblanchon.github.io/ArduinoJson/doc/pitfalls/)
|
||||
- [API Reference](https://bblanchon.github.io/ArduinoJson/api/)
|
||||
- ~~[Migrating code to new the API](Migrating code to the new API)~~ (obsolete)
|
||||
|
||||
#### Resources
|
||||
|
||||
- [F.A.Q (Frequently Asked Questions) :confused:](https://bblanchon.github.io/ArduinoJson/faq/)
|
||||
- [Examples](Examples)
|
||||
- [Bag of Tricks](Bag of Tricks)
|
||||
- [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant/)
|
||||
|
||||
@@ -29,4 +29,4 @@
|
||||
#### Misc
|
||||
- [Contributing](Contributing)
|
||||
- [Projects using Arduno JSON library](Projects using ArduinoJson)
|
||||
- [Donations](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :beers:
|
||||
- [Donations](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :beers:
|
||||
|
108
Memory-model.md
108
Memory-model.md
@@ -1,107 +1 @@
|
||||
> *This page explains how the memory is managed in the Arduino JSON library*
|
||||
|
||||
## Fixed memory allocation
|
||||
|
||||
### Introducing `StaticJsonBuffer`
|
||||
|
||||
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer` class.
|
||||
|
||||
Before using any function of the library you need to create a `StaticJsonBuffer`. Then you can use this instance to create arrays and objects, or parse a JSON string.
|
||||
|
||||
`StaticJsonBuffer` has a template parameter that determines its capacity. For example, the following line creates a `StaticJsonBuffer` with a capacity of 200 bytes:
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
The bigger the buffer is, the more complex the object tree can be, but also the more memory you need.
|
||||
|
||||
### How to determine the buffer size?
|
||||
|
||||
So the big question you should have in mind right now is *How can I determine the size?*.
|
||||
|
||||
There are basically two approaches here:
|
||||
|
||||
1. either you can predict the content of the object tree,
|
||||
2. or, you know how much memory is available.
|
||||
|
||||
In the first case, you know some constraints on the object tree. For instance, let's say that you know in advance (and by that I mean "at compilation time") that you want to generate an object with 3 values, one of them being an array with 2 values, like the following:
|
||||
|
||||
{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
To determine the memory usage of this object tree, you use the two macros `JSON_ARRAY_SIZE(n)` and `JSON_OBJECT_SIZE(n)`, both take the number of elements as an argument.
|
||||
For the example above, it would be:
|
||||
|
||||
const int BUFFER_SIZE = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2);
|
||||
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
|
||||
|
||||
If you're in this situation, [ArduinoJson Assistant](https://bblanchon.github.io/ArduinoJson/assistant) will be of great help.
|
||||
|
||||
In the second case, let's say you dynamically generate a JSON object tree of a random complexity so you can't put a limit based on that. But on the other hand, you don't want your program to crash because the object tree doesn't fit in memory.
|
||||
The solution here is to determine how much memory is available, or in other words how much memory you can afford for the JSON object tree.
|
||||
|
||||
### Why choose fixed allocation?
|
||||
|
||||
This fixed allocation approach may seem a bit strange, especially if you are a desktop application developer used to dynamic allocation, but it makes a lot of sense in an embedded context:
|
||||
|
||||
1. the code is smaller
|
||||
2. it uses less memory
|
||||
3. it doesn't create memory fragmentation
|
||||
4. it is predictable
|
||||
|
||||
Don't forget that the memory is "freed" as soon as the `StaticJsonBuffer` is out of scope, like any other variable. It only holds the memory for a short amount of time.
|
||||
|
||||
## Dynamic memory allocation
|
||||
|
||||
This library also supports dynamic memory allocation.
|
||||
|
||||
However, usage of this memory model is **strongly discouraged** in embedded environments.
|
||||
|
||||
To switch to dynamic memory allocation, simply replace:
|
||||
|
||||
StaticJsonBuffer<N> jsonBuffer;
|
||||
|
||||
by
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
Memory is released in `DynamicJsonBuffer`'s destructor, so you don't have to do anything special.
|
||||
|
||||
## Memory usage
|
||||
|
||||
#### Object size for 8-bit AVR
|
||||
|
||||
| Type | Size |
|
||||
|-------------------------|------------|
|
||||
| JsonArray of N element | 4 + 8 * N |
|
||||
| JsonObject of N element | 4 + 10 * N |
|
||||
|
||||
#### Object size on ESP8266
|
||||
|
||||
| Type | Size |
|
||||
|-------------------------|------------|
|
||||
| JsonVariant | 8 |
|
||||
| JsonArray of N element | 8 + 12 * N |
|
||||
| JsonObject of N element | 8 + 16 * N |
|
||||
|
||||
#### Object size on ESP8266 if `JsonFloat` is changed to `double`
|
||||
|
||||
| Type | Size |
|
||||
|-------------------------|------------|
|
||||
| JsonVariant | 16 |
|
||||
| JsonArray of N element | 8 + 24 * N |
|
||||
| JsonObject of N element | 8 + 32 * N |
|
||||
|
||||
#### Object size on x86 (tested on Visual Studio 2015)
|
||||
|
||||
| Type | Size |
|
||||
|-------------------------|-------------|
|
||||
| JsonVariant | 16 |
|
||||
| JsonArray of N element | 12 + 24 * N |
|
||||
| JsonObject of N element | 12 + 32 * N |
|
||||
|
||||
#### Object size on x64 (tested on Visual Studio 2015)
|
||||
|
||||
| Type | Size |
|
||||
|-------------------------|-------------|
|
||||
| JsonVariant | 16 |
|
||||
| JsonArray of N element | 24 + 24 * N |
|
||||
| JsonObject of N element | 24 + 32 * N |
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/doc/memory/ 🚚
|
||||
|
@@ -1,25 +1 @@
|
||||
All you need to write a `CMakeLists.txt` like this one:
|
||||
|
||||
```CMake
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
project(Server)
|
||||
|
||||
add_subdirectory(ArduinoJson/src)
|
||||
|
||||
add_executable(server
|
||||
server.c
|
||||
)
|
||||
|
||||
target_link_libraries(server ArduinoJson)
|
||||
```
|
||||
|
||||
Then just call:
|
||||
|
||||
```shell
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
See issue [#188](https://github.com/bblanchon/ArduinoJson/issues/188)
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/doc/installation/ 🚚
|
||||
|
@@ -1,48 +1 @@
|
||||
This library is primarily design to be used with the Arduino IDE and therefore has a simplified setup procedure for that environment.
|
||||
If you don't use the Arduino IDE, please read [Using the library without Arduino](Using the library without Arduino).
|
||||
|
||||
## Install the library
|
||||
|
||||
### For Arduino 1.6.x and above
|
||||
|
||||
ArduinoJson is available in Arduino's Library Manager.
|
||||
You can automatically install it from there.
|
||||
|
||||
Note: if ArduinoJson doesn't appear in Library Manager, or if only old versions are listed, try to delete the local cache. For example, on Windows, you need to delete:
|
||||
|
||||
* `%LOCALAPPDATA%\Arduino15\library_index.json`
|
||||
* `%LOCALAPPDATA%\Arduino15\library_index.json.tmp.gz`
|
||||
|
||||
You don't even need to close Arduino, just re-open the library manager.
|
||||
|
||||
|
||||
### For older Arduino IDE
|
||||
|
||||
You needed to [download the zip package](https://github.com/bblanchon/ArduinoJson/releases) and extract it to:
|
||||
|
||||
<your Arduino Sketch folder>/libraries/ArduinoJson
|
||||
|
||||
Then restart the Arduino IDE.
|
||||
|
||||
**NOTE**: There are two packages the standard and the "old-layout". You need to use the "old-layout" for Arduino 1.0.X, Energia and other alternative IDE.
|
||||
|
||||
### For Visual Micro / Visual Studio 2015 / Atmel Studio
|
||||
|
||||
You need the latest version (January 2016 or later) of [Visual Micro](http://www.visualmicro.com) installed for Visual Studio or Atmel Studio.
|
||||
|
||||
## Run the examples sketches
|
||||
|
||||
Click `File` / `Example` / `ArduinoJson`.
|
||||
|
||||

|
||||
|
||||
## Use the library in your sketches
|
||||
|
||||
Just add the following line at the top of your program:
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
Then follow the instructions:
|
||||
|
||||
1. [Decoding JSON](Decoding JSON)
|
||||
2. [Encoding JSON](Encoding JSON)
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/doc/installation/ 🚚
|
||||
|
@@ -1,8 +1 @@
|
||||
ArduinoJson is a header-only library, so you just need to [download](https://github.com/bblanchon/ArduinoJson/releases) the package and unzip it in a convenient location.
|
||||
|
||||
Then add the `include/` folder to your compiler's or your IDE's include directories.
|
||||
|
||||
See next:
|
||||
|
||||
1. [Parsing JSON](Decoding-JSON)
|
||||
2. [Generating JSON](Encoding-JSON)
|
||||
🚚 This page has been moved to https://bblanchon.github.io/ArduinoJson/doc/installation/ 🚚
|
||||
|
@@ -1 +0,0 @@
|
||||
This wiki probably contains a few mistakes, please help other users by fixing it :kissing_smiling_eyes:
|
Reference in New Issue
Block a user