forked from bblanchon/ArduinoJson
Compare commits
44 Commits
v5.12.0
...
v6.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
e86eb0cfdf | |||
a9a730fd74 | |||
4ff6809bc5 | |||
7b229e4c38 | |||
9ac9b533b6 | |||
f53fc3e06f | |||
0139354780 | |||
011aac43d2 | |||
eb20ae6a3f | |||
7c0af91844 | |||
fc2e3a4ab3 | |||
58cb793c96 | |||
4592f23260 | |||
ccb54136a2 | |||
4c9c047ddf | |||
1feb92679d | |||
a13b9e8bdc | |||
cb723840d9 | |||
923d3e8a84 | |||
0d1623edef | |||
cf149940ed | |||
ef55a6ba7c | |||
e3e4aa89ad | |||
3523296e3d | |||
b2a8085651 | |||
83d73c93f7 | |||
7a2a64803a | |||
baf5adcf33 | |||
689ae5c08d | |||
d9b1e7e810 | |||
b4eece01f8 | |||
cf5396aaed | |||
e390587e91 | |||
bae179ed67 | |||
7e4fcb0868 | |||
fbfdca1de9 | |||
0612eef69b | |||
ae0b7a3ebd | |||
e92612b511 | |||
5c33fd4b94 | |||
c3f51e2980 | |||
de47c0af9e | |||
e53e4e3dd9 | |||
36fe6535c4 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@
|
||||
/fuzzing/*_fuzzer
|
||||
/fuzzing/*_fuzzer.options
|
||||
/fuzzing/*_fuzzer_seed_corpus.zip
|
||||
.vs/
|
||||
|
38
.travis.yml
38
.travis.yml
@ -2,12 +2,6 @@ sudo: false
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.4']
|
||||
env: SCRIPT=cmake GCC=4.4
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -37,7 +31,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=cmake GCC=5 SANITIZE=undefined
|
||||
env: SCRIPT=cmake GCC=5 # SANITIZE=undefined
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -76,6 +70,30 @@ matrix:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-precise-3.8']
|
||||
packages: ['clang-3.8']
|
||||
env: SCRIPT=cmake CLANG=3.8 SANITIZE=undefined
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-3.9']
|
||||
packages: ['clang-3.9']
|
||||
env: SCRIPT=cmake CLANG=3.9
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-4.0']
|
||||
packages: ['clang-4.0']
|
||||
env: SCRIPT=cmake CLANG=4.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-5.0']
|
||||
packages: ['clang-5.0']
|
||||
env: SCRIPT=cmake CLANG=5.0
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0']
|
||||
env: SCRIPT=cmake CLANG=6.0
|
||||
- compiler: gcc
|
||||
env: SCRIPT=coverage
|
||||
- os: osx
|
||||
@ -90,6 +108,12 @@ matrix:
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=platformio BOARD=uno
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test','llvm-toolchain-trusty-6.0']
|
||||
packages: ['clang-6.0','llvm-6.0']
|
||||
env: SCRIPT=fuzz CLANG=6.0
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#include "src/ArduinoJson.h"
|
||||
|
97
CHANGELOG.md
97
CHANGELOG.md
@ -1,10 +1,105 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v6.0.0-beta
|
||||
-----------
|
||||
|
||||
* Added `DynamicJsonDocument` and `StaticJsonDocument`
|
||||
* Added `deserializeJson()`
|
||||
* Added `serializeJson()` and `serializeJsonPretty()`
|
||||
* Added `measureJson()` and `measureJsonPretty()`
|
||||
* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358)
|
||||
* Added example `MsgPackParser.ino` (issue #358)
|
||||
* Added support for non zero-terminated strings (issue #704)
|
||||
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
|
||||
* Removed `JsonBuffer::createArray()` and `createObject()`
|
||||
* Removed `printTo()` and `prettyPrintTo()`
|
||||
* Removed `measureLength()` and `measurePrettyLength()`
|
||||
* Removed all deprecated features
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Deserialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.parseObject(json);
|
||||
> if (obj.success()) {
|
||||
>
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> DeserializationError error = deserializeJson(doc, json);
|
||||
> if (error) {
|
||||
>
|
||||
> }
|
||||
> JsonObject& obj = doc.as<JsonObject>();
|
||||
> ```
|
||||
>
|
||||
> #### Serialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.createObject();
|
||||
> obj["key"] = "value";
|
||||
> obj.printTo(Serial);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument obj;
|
||||
> JsonObject& obj = doc.to<JsonObject>();
|
||||
> obj["key"] = "value";
|
||||
> serializeJson(doc, Serial);
|
||||
> ```
|
||||
|
||||
v5.13.2
|
||||
-------
|
||||
|
||||
* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693)
|
||||
* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu)
|
||||
* Fixed null values that could be pass to `strcmp()` (PR #745 from Mike Karlesky)
|
||||
* Added macros `ARDUINOJSON_VERSION`, `ARDUINOJSON_VERSION_MAJOR`...
|
||||
|
||||
v5.13.1
|
||||
-------
|
||||
|
||||
* Fixed `JsonVariant::operator|(int)` that returned the default value if the variant contained a double (issue #675)
|
||||
* Allowed non-quoted key to contain underscores (issue #665)
|
||||
|
||||
v5.13.0
|
||||
-------
|
||||
|
||||
* Changed the rules of string duplication (issue #658)
|
||||
* `RawJson()` accepts any kind of string and obeys to the same rules for duplication
|
||||
* Changed the return type of `strdup()` to `const char*` to prevent double duplication
|
||||
* Marked `strdup()` as deprecated
|
||||
|
||||
> ### New rules for string duplication
|
||||
>
|
||||
> | type | duplication |
|
||||
> |:---------------------------|:------------|
|
||||
> | const char* | no |
|
||||
> | char* | ~~no~~ yes |
|
||||
> | String | yes |
|
||||
> | std::string | yes |
|
||||
> | const __FlashStringHelper* | yes |
|
||||
>
|
||||
> These new rules make `JsonBuffer::strdup()` useless.
|
||||
|
||||
v5.12.0
|
||||
-------
|
||||
|
||||
* Added `JsonVariant::operator|` to return a default value (see bellow)
|
||||
* Added `JsonVariant::operator|` to return a default value (see below)
|
||||
* Added a clear error message when compiled as C instead of C++ (issue #629)
|
||||
* Added detection of MPLAB XC compiler (issue #629)
|
||||
* Added detection of Keil ARM Compiler (issue #629)
|
||||
|
@ -1,5 +1,5 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2017
|
||||
# Copyright Benoit Blanchon 2014-2018
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
@ -1,7 +1,7 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014-2017 Benoit BLANCHON
|
||||
Copyright © 2014-2018 Benoit BLANCHON
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
149
README.md
149
README.md
@ -1,74 +1,85 @@
|
||||

|
||||
|
||||
---
|
||||
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||

|
||||
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
ArduinoJson - C++ JSON library for IoT
|
||||
====================
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc).
|
||||
|
||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
|
||||
For instance, it supports Aduino's `String` and `Stream`, but also `std::string`, `std::istream` and `std::ostream`.
|
||||
|
||||
Features
|
||||
--------
|
||||
## Features
|
||||
|
||||
* JSON decoding (comments are supported)
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, very easy to use
|
||||
* MessagePack
|
||||
* Elegant API, easy to use
|
||||
* Fixed memory allocation (zero malloc)
|
||||
* No data duplication (zero copy)
|
||||
* Portable (written in C++98)
|
||||
* Portable (written in C++98, can be used in any C++ project)
|
||||
* Self-contained (no external dependency)
|
||||
* Small footprint
|
||||
* Header-only library
|
||||
* MIT License
|
||||
* [Comprehensive documentation](https://arduinojson.org)
|
||||
* Input and output streams
|
||||
* [100% code coverage](https://coveralls.io/github/bblanchon/ArduinoJson)
|
||||
* [Header-only library](https://en.wikipedia.org/wiki/Header-only)
|
||||
* [MIT License](https://en.wikipedia.org/wiki/MIT_License)
|
||||
* [Comprehensive documentation](https://arduinojson.org?utm_source=github&utm_medium=readme)
|
||||
|
||||
Works on
|
||||
--------
|
||||
## Compatibility
|
||||
|
||||
* Arduino boards: Uno, Due, Mini, Micro, Yun...
|
||||
* ESP8266, ESP32
|
||||
* Teensy
|
||||
* RedBearLab boards (BLE Nano...)
|
||||
* Intel Edison and Galileo
|
||||
* WeMos boards: D1...
|
||||
* Computers: Windows, Linux, OSX...
|
||||
* PlatformIO
|
||||
* Particle
|
||||
* Energia
|
||||
ArduinoJson works on the following hardware:
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
* <img src="https://www.arduino.cc/favicon.ico" height="16" width="16"> Arduino boards: [Uno](https://www.arduino.cc/en/Main/ArduinoBoardUno), [Due](https://www.arduino.cc/en/Main/ArduinoBoardDue), [Mini](https://www.arduino.cc/en/Main/ArduinoBoardMini), [Micro](https://www.arduino.cc/en/Main/ArduinoBoardMicro), [Yun](https://www.arduino.cc/en/Main/ArduinoBoardYun)...
|
||||
* <img src="http://espressif.com/sites/all/themes/espressif/favicon.ico" height="16" width="16"> Espressif chips: [ESP8266](https://en.wikipedia.org/wiki/ESP8266), [ESP32](https://en.wikipedia.org/wiki/ESP32)
|
||||
* <img src="https://www.wemos.cc/themes/martin-materialize-parallax/assets/favicon.ico" height="16" width="16"> WeMos boards: [D1](https://wiki.wemos.cc/products:d1:d1), [D1 mini](https://wiki.wemos.cc/products:d1:d1_mini), ...
|
||||
* <img src="http://redbearlab.com/favicon.ico" height="16" width="16"> RedBearLab boards: [BLE Nano](http://redbearlab.com/blenano/), [BLE Mini](http://redbearlab.com/blemini/), [WiFi Micro](https://redbear.cc/product/wifi/wifi-micro.html), [LOLIN32](https://wiki.wemos.cc/products:lolin32:lolin32)...
|
||||
* <img src="https://www.pjrc.com/favicon.ico" height="16" width="16"> [Teensy](https://www.pjrc.com/teensy/) boards
|
||||
* <img src="https://software.intel.com/sites/all/themes/zero/favicon.ico" height="16" width="16"> Intel boards: Edison, Galileo...
|
||||
* <img src="https://www-assets.particle.io/images/favicon.png" height="16" width="16"> Particle boards: [Photon](https://www.particle.io/products/hardware/photon-wifi-dev-kit), [Electron](https://www.particle.io/products/hardware/electron-cellular-dev-kit)...
|
||||
* <img src="http://www.ti.com/favicon.ico" height="16" width="16"> Texas Instruments boards: [MSP430](http://www.ti.com/microcontrollers/msp430-ultra-low-power-mcus/overview/overview.html)...
|
||||
|
||||
#### Decoding / Parsing
|
||||
ArduinoJson compiles with zero warning on the following compilers, IDEs, and platforms:
|
||||
|
||||
* <img src="https://www.arduino.cc/favicon.ico" height="16" width="16"> [Arduino IDE](https://www.arduino.cc/en/Main/Software)
|
||||
* <img src="http://cdn.platformio.org/favicon.ico" height="16" width="16"> [PlatformIO](http://platformio.org/)
|
||||
* <img src="http://energia.nu/img/favicon.ico" height="16" width="16"> [Energia](http://energia.nu/)
|
||||
* <img src="http://www.visualmicro.com/pics/arduino-visual-studio-ld.png" height="16" width="16"> [Visual Micro](http://www.visualmicro.com/)
|
||||
* <img src="http://www.atmel.com/Images/favicon.ico" height="16" width="16"> [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/)
|
||||
* <img src="https://www.iar.com/favicon.ico" height="16" width="16"> [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/)
|
||||
* <img src="http://www.st.com/etc/clientlibs/st-site/media/app/images/favicon.png" height="16" width="16"> [Atollic TrueSTUDIO](https://atollic.com/truestudio/)
|
||||
* <img src="http://www.keil.com/favicon.ico" height="16" width="16"> [Keil uVision](http://www.keil.com/)
|
||||
* <img src="http://www.microchip.com/favicon.ico" height="16" width="16"> [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide)
|
||||
* <img src="https://gcc.gnu.org/favicon.ico" height="16" width="16"> [GCC](https://gcc.gnu.org/)
|
||||
* <img src="https://clang.llvm.org/favicon.ico" height="16" width="16"> [Clang](https://clang.llvm.org/)
|
||||
* <img src="https://www.visualstudio.com/favicon.ico" height="16" width="16"> [Visual Studio](https://www.visualstudio.com/)
|
||||
|
||||
## Quickstart
|
||||
|
||||
### Deserialization
|
||||
|
||||
Here is a program that parses a JSON document with ArduinoJson.
|
||||
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
DynamicJsonDocument doc;
|
||||
deserializeJson(doc, json);
|
||||
|
||||
JsonObject& root = doc.as<JsonObject>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
```
|
||||
|
||||
[See JsonParserExample.ino](https://arduinojson.org/example/parser/)
|
||||
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
|
||||
|
||||
Use [ArduinoJson Assistant](https://arduinojson.org/assistant/) to compute the buffer size.
|
||||
### Serialization
|
||||
|
||||
#### Encoding / Generating
|
||||
Here is a program that generates a JSON document with ArduinoJson:
|
||||
|
||||
```c++
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
JsonObject& root = doc.to<JsonObject>();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
@ -76,57 +87,25 @@ JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
serializeJson(doc, Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
```
|
||||
|
||||
[See JsonGeneratorExample.ino](https://arduinojson.org/example/generator/)
|
||||
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme)
|
||||
|
||||
Use [ArduinoJson Assistant](https://arduinojson.org/assistant/) to compute the buffer size.
|
||||
## Documentation
|
||||
|
||||
The documentation is available on [arduinojson.org](https://arduinojson.org/?utm_source=github&utm_medium=readme), here are some shortcuts:
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The documentation is available online in the [ArduinoJson Website](https://arduinojson.org/).
|
||||
|
||||
The [ArduinoJson Assistant](https://arduinojson.org/assistant/) helps you get started with the library.
|
||||
|
||||
|
||||
Donators
|
||||
--------
|
||||
|
||||
Special thanks to the following persons and companies who made generous donations to the library author:
|
||||
|
||||
* Robert Murphy <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Surge Communications <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Alex Scott <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
|
||||
* Firepick Services LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* A B Doodkorte <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Scott Smith <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Johann Stieger <img alt='Austria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e6-1f1f9.svg' width='18' height='18'>
|
||||
* Gustavo Donizeti Gini <img alt='Brazil' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e7-1f1f7.svg' width='18' height='18'>
|
||||
* Charles-Henri Hallard <img alt='France' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1eb-1f1f7.svg' width='18' height='18'>
|
||||
* Martijn van den Burg <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Nick Koumaris <img alt='Greece' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1f7.svg' width='18' height='18'>
|
||||
* Jon Williams <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Kestutis Liaugminas <img alt='Lithuania' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1f9.svg' width='18' height='18'>
|
||||
* Darlington Adibe <img alt='Nigeria' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1ec.svg' width='18' height='18'>
|
||||
* Yoeri Kroon <img alt='Netherlands' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f3-1f1f1.svg' width='18' height='18'>
|
||||
* Andrew Melvin <img alt='United Kingdom' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1ec-1f1e7.svg' width='18' height='18'>
|
||||
* Doanh Luong <img alt ='Vietnam' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fb-1f1f3.svg' width='18' height='18'>
|
||||
* Christoph Schmidt <img alt='Germany' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e9-1f1ea.svg' width='18' height='18'>
|
||||
* OpenEVSE LLC <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Prokhoryatov Alexey <img alt='Russia' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f7-1f1fa.svg' width='18' height='18'>
|
||||
* Google Inc. <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Charles Haynes <img alt='Australia' src='https://d1j8pt39hxlh3d.cloudfront.net/development/emojione/2.2/989/2546.svg' width='18' height='18'>
|
||||
* Charles Walker <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Günther Jehle <img alt='Liechtenstein' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1ee.svg' width='18' height='18'>
|
||||
* Patrick Elliott
|
||||
* Alexander Wilms <img alt='Germany' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1e9-1f1ea.svg' width='18' height='18'>
|
||||
|
||||
* The [Examples](https://arduinojson.org/example/?utm_source=github&utm_medium=readme) show how to use the library in various situations.
|
||||
* The [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=readme) contains the description of each class and function.
|
||||
* The [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=readme) has the answer to virtually every question.
|
||||
* The [ArduinoJson Assistant](https://arduinojson.org/assistant/?utm_source=github&utm_medium=readme) writes programs for you!
|
||||
|
||||
---
|
||||
|
||||
Found this library useful? Please star this project or [help me back with a donation!](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) :smile:
|
||||
Do you like this library? Please [star this project on GitHub](https://github.com/bblanchon/ArduinoJson/stargazers)!
|
||||
|
||||
What? You don't like it but you *love* it?
|
||||
We don't take donations anymore, but [we sell a book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme), so you can help and learn at the same time!
|
||||
|
@ -6,8 +6,8 @@ We'll be very happy to help you, but first please read the following.
|
||||
|
||||
## Before asking for help
|
||||
|
||||
1. Read the [FAQ](https://arduinojson.org/faq/)
|
||||
2. Search in the [API Reference](https://arduinojson.org/api/)
|
||||
1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support)
|
||||
2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support)
|
||||
|
||||
If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 5.12.0.{build}
|
||||
version: 6.0.0.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to store your project configuration in a file.
|
||||
@ -29,17 +29,19 @@ void loadConfiguration(const char *filename, Config &config) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
|
||||
// Allocate the memory pool on the stack.
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Allocate the document on the stack.
|
||||
// Don't forget to change the capacity to match your requirements.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<512> jsonBuffer;
|
||||
StaticJsonDocument<512> doc;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.parseObject(file);
|
||||
|
||||
if (!root.success())
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, file);
|
||||
if (error)
|
||||
Serial.println(F("Failed to read file, using default configuration"));
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject &root = doc.as<JsonObject>();
|
||||
|
||||
// Copy values from the JsonObject to the Config
|
||||
config.port = root["port"] | 2731;
|
||||
strlcpy(config.hostname, // <- destination
|
||||
@ -62,20 +64,20 @@ void saveConfiguration(const char *filename, const Config &config) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the memory pool on the stack
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use https://arduinojson.org/assistant/ to compute the capacity.
|
||||
StaticJsonBuffer<256> jsonBuffer;
|
||||
// Allocate the document on the stack.
|
||||
// Don't forget to change the capacity to match your requirements.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<256> doc;
|
||||
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.createObject();
|
||||
// Make our document contain an object
|
||||
JsonObject &root = doc.to<JsonObject>();
|
||||
|
||||
// Set the values
|
||||
// Set the values in the object
|
||||
root["hostname"] = config.hostname;
|
||||
root["port"] = config.port;
|
||||
|
||||
// Serialize JSON to file
|
||||
if (root.printTo(file) == 0) {
|
||||
if (serializeJson(doc, file) == 0) {
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
|
||||
@ -141,4 +143,4 @@ void loop() {
|
||||
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
||||
// a complex configuration with nested members.
|
||||
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
@ -11,24 +11,20 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
// The JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Inside the brackets, 200 is the RAM allocated to this document.
|
||||
// Don't forget to change this value to match your requirement.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
// DynamicJsonDocument doc(200);
|
||||
|
||||
// Create the root of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
// Make our document be an object
|
||||
JsonObject& root = doc.to<JsonObject>();
|
||||
|
||||
// Add values in the object
|
||||
//
|
||||
@ -37,21 +33,19 @@ void setup() {
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
// Add a nested array.
|
||||
// Add an array.
|
||||
//
|
||||
// It's also possible to create the array separately and add it to the
|
||||
// JsonObject but it's less efficient.
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
root.printTo(Serial);
|
||||
serializeJson(root, Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
Serial.println();
|
||||
|
||||
root.prettyPrintTo(Serial);
|
||||
serializeJsonPretty(root, Serial);
|
||||
// This prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
@ -78,4 +72,4 @@ void loop() {
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like serializing directly to a file or an HTTP request.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
@ -1,9 +1,9 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to parse a JSON document in an HTTP response.
|
||||
// It uses the Ethernet library, but can be easily adapter for Wifi.
|
||||
// It uses the Ethernet library, but can be easily adapted for Wifi.
|
||||
//
|
||||
// It performs a GET resquest on arduinojson.org/example.json
|
||||
// Here is the expected response:
|
||||
@ -70,19 +70,21 @@ void setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate JsonBuffer
|
||||
// Allocate the JSON document
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
|
||||
DynamicJsonBuffer jsonBuffer(capacity);
|
||||
DynamicJsonDocument doc(capacity);
|
||||
|
||||
// Parse JSON object
|
||||
JsonObject& root = jsonBuffer.parseObject(client);
|
||||
if (!root.success()) {
|
||||
Serial.println(F("Parsing failed!"));
|
||||
DeserializationError error = deserializeJson(doc, client);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract values
|
||||
JsonObject& root = doc.as<JsonObject>();
|
||||
Serial.println(F("Response:"));
|
||||
Serial.println(root["sensor"].as<char*>());
|
||||
Serial.println(root["time"].as<char*>());
|
||||
@ -109,4 +111,4 @@ void loop() {
|
||||
// showing how to parse the response from Yahoo Weather. In the last chapter,
|
||||
// it shows how to parse the huge documents from OpenWeatherMap
|
||||
// and Weather Underground.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
@ -11,17 +11,17 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Memory pool for JSON object tree.
|
||||
// Root JSON object
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
// DynamicJsonObject doc(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
@ -31,23 +31,23 @@ void setup() {
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
// Root of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, json);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (!root.success()) {
|
||||
Serial.println("parseObject() failed");
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject& root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root["time"].as<long>();
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
@ -75,4 +75,4 @@ void loop() {
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like deserializing directly from a file or an HTTP request.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
@ -1,10 +1,10 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to implement an HTTP server that sends JSON document
|
||||
// in the responses.
|
||||
// It uses the Ethernet library but can be easily adapter for Wifi.
|
||||
// It uses the Ethernet library but can be easily adapted for Wifi.
|
||||
//
|
||||
// It sends the value of the analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
@ -51,12 +51,12 @@ void loop() {
|
||||
// Read the request (we ignore the content in this example)
|
||||
while (client.available()) client.read();
|
||||
|
||||
// Allocate JsonBuffer
|
||||
// Allocate the JSON document
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
StaticJsonDocument<500> doc;
|
||||
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
// Make our document represent an object
|
||||
JsonObject& root = doc.to<JsonObject>();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
@ -79,7 +79,7 @@ void loop() {
|
||||
}
|
||||
|
||||
Serial.print(F("Sending: "));
|
||||
root.printTo(Serial);
|
||||
serializeJson(root, Serial);
|
||||
Serial.println();
|
||||
|
||||
// Write response headers
|
||||
@ -89,7 +89,7 @@ void loop() {
|
||||
client.println();
|
||||
|
||||
// Write JSON document
|
||||
root.prettyPrintTo(client);
|
||||
serializeJsonPretty(root, client);
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
@ -106,4 +106,4 @@ void loop() {
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or an HTTP client.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
@ -1,8 +1,8 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to JSON document to a UDP socket.
|
||||
// This example shows how to send a JSON document to a UDP socket.
|
||||
// At regular interval, it sends a UDP packet that contains the status of
|
||||
// analog and digital pins.
|
||||
// The JSON document looks like the following:
|
||||
@ -43,12 +43,12 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Allocate JsonBuffer
|
||||
// Allocate the JSON document
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
StaticJsonDocument<500> doc;
|
||||
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
// Make our document represent an object
|
||||
JsonObject& root = doc.to<JsonObject>();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
@ -75,11 +75,11 @@ void loop() {
|
||||
Serial.print(remoteIp);
|
||||
Serial.print(F(" on port "));
|
||||
Serial.println(remotePort);
|
||||
root.printTo(Serial);
|
||||
serializeJson(root, Serial);
|
||||
|
||||
// Send UDP packet
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
root.printTo(udp);
|
||||
serializeJson(root, udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
|
||||
@ -98,4 +98,4 @@ void loop() {
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or any stream.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
91
examples/MsgPackParser/MsgPackParser.ino
Normal file
91
examples/MsgPackParser/MsgPackParser.ino
Normal file
@ -0,0 +1,91 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a MessagePack document with
|
||||
// ArduinoJson.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
|
||||
// MessagePack input string.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
|
||||
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
|
||||
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
|
||||
112, 203, 64, 2, 106, 146, 230, 33, 49, 169};
|
||||
// This MessagePack document contains:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [48.75608, 2.302038]
|
||||
// }
|
||||
|
||||
// doc of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
Serial.print("deserializeMsgPack() failed: ");
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject& root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do doc["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
// Print values.
|
||||
Serial.println(sensor);
|
||||
Serial.println(time);
|
||||
Serial.println(latitude, 6);
|
||||
Serial.println(longitude, 6);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// The website arduinojson.org contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// deserialization problem.
|
||||
// Please check it out at: https://arduinojson.org/
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like deserializing directly from a file or an HTTP request.
|
||||
// Please check it out at: https://arduinojson.org/book/
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows the different ways you can use Flash strings with
|
||||
@ -14,31 +14,34 @@
|
||||
void setup() {
|
||||
#ifdef PROGMEM // <- check that Flash strings are supported
|
||||
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
// You can use a Flash String as your JSON input.
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
JsonObject& root =
|
||||
jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
// You can use a Flash String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = root[F("time")];
|
||||
long time = obj[F("time")];
|
||||
|
||||
// You can use a Flash String to set an element of a JsonObject
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
root[F("time")] = time;
|
||||
obj[F("time")] = time;
|
||||
|
||||
// You can set a Flash String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
root["sensor"] = F("gps");
|
||||
obj["sensor"] = F("gps");
|
||||
|
||||
// It works with RawJson too:
|
||||
obj["sensor"] = RawJson(F("\"gps\""));
|
||||
|
||||
// You can compare the content of a JsonVariant to a Flash String
|
||||
if (root["sensor"] == F("gps")) {
|
||||
if (obj["sensor"] == F("gps")) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@ -64,4 +67,4 @@ void loop() {
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. It also tells why you
|
||||
// should not abuse Flash strings with ArduinoJson.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows the different ways you can use String with ArduinoJson.
|
||||
@ -11,47 +11,51 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
DynamicJsonDocument doc;
|
||||
|
||||
// You can use a String as your JSON input.
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
String input =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
JsonObject& root = jsonBuffer.parseObject(input);
|
||||
deserializeJson(doc, input);
|
||||
JsonObject& obj = doc.as<JsonObject>();
|
||||
|
||||
// You can use a String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = root[String("time")];
|
||||
long time = obj[String("time")];
|
||||
|
||||
// You can use a String to set an element of a JsonObject
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root[String("time")] = time;
|
||||
obj[String("time")] = time;
|
||||
|
||||
// You can get a String from a JsonObject or JsonArray:
|
||||
// No duplication is done, at least not in the JsonBuffer.
|
||||
String sensor = root["sensor"];
|
||||
String sensor = obj["sensor"];
|
||||
|
||||
// Unfortunately, the following doesn't work (issue #118):
|
||||
// sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='"
|
||||
// sensor = obj["sensor"]; // <- error "ambiguous overload for 'operator='"
|
||||
// As a workaround, you need to replace by:
|
||||
sensor = root["sensor"].as<String>();
|
||||
sensor = obj["sensor"].as<String>();
|
||||
|
||||
// You can set a String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root["sensor"] = sensor;
|
||||
obj["sensor"] = sensor;
|
||||
|
||||
// It works with RawJson too:
|
||||
obj["sensor"] = RawJson(sensor);
|
||||
|
||||
// You can also concatenate strings
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
root[String("sen") + "sor"] = String("gp") + "s";
|
||||
obj[String("sen") + "sor"] = String("gp") + "s";
|
||||
|
||||
// You can compare the content of a JsonObject with a String
|
||||
if (root["sensor"] == sensor) {
|
||||
if (obj["sensor"] == sensor) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Lastly, you can print the resulting JSON to a String
|
||||
String output;
|
||||
root.printTo(output);
|
||||
serializeJson(doc, output);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
@ -68,4 +72,4 @@ void loop() {
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. On several occasions, it
|
||||
// shows how you can avoid String in your program.
|
||||
// Please check it out at: https://leanpub.com/arduinojson/
|
||||
// Please check it out at: https://arduinojson.org/book/
|
||||
|
@ -5,15 +5,18 @@ CXXFLAGS += -I../src
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/json_fuzzer.options
|
||||
$(OUT)/json_fuzzer.options \
|
||||
$(OUT)/msgpack_fuzzer \
|
||||
$(OUT)/msgpack_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/msgpack_fuzzer.options
|
||||
|
||||
$(OUT)/json_fuzzer: fuzzer.cpp $(shell find ../src -type f)
|
||||
$(OUT)/%_fuzzer: %_fuzzer.cpp $(shell find ../src -type f)
|
||||
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
|
||||
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/*
|
||||
$(OUT)/%_fuzzer_seed_corpus.zip: %_seed_corpus/*
|
||||
zip -j $@ $?
|
||||
|
||||
$(OUT)/json_fuzzer.options:
|
||||
$(OUT)/%_fuzzer.options:
|
||||
@echo "[libfuzzer]" > $@
|
||||
@echo "max_len = 256" >> $@
|
||||
@echo "timeout = 10" >> $@
|
||||
|
@ -1,9 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This script mimics an invocation from https://github.com/google/oss-fuzz
|
||||
|
||||
cd $(dirname $0)
|
||||
export CXX='clang++'
|
||||
export CXXFLAGS='-fsanitize-coverage=trace-pc-guard -fsanitize=address'
|
||||
export LIB_FUZZING_ENGINE=-lFuzzer
|
||||
make OUT=.
|
||||
./json_fuzzer my_corpus seed_corpus -max_len=1024 -timeout=10
|
@ -1,26 +0,0 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class memstream : public std::istream {
|
||||
struct membuf : std::streambuf {
|
||||
membuf(const uint8_t *p, size_t l) {
|
||||
setg((char *)p, (char *)p, (char *)p + l);
|
||||
}
|
||||
};
|
||||
membuf _buffer;
|
||||
|
||||
public:
|
||||
memstream(const uint8_t *p, size_t l)
|
||||
: std::istream(&_buffer), _buffer(p, l) {
|
||||
rdbuf(&_buffer);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
memstream json(data, size);
|
||||
JsonVariant variant = jsonBuffer.parse(json);
|
||||
if (variant.success()) {
|
||||
variant.as<std::string>(); // <- serialize to JSON
|
||||
}
|
||||
return 0;
|
||||
}
|
11
fuzzing/json_fuzzer.cpp
Normal file
11
fuzzing/json_fuzzer.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
2
fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
2
fuzzing/msgpack_corpus/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
11
fuzzing/msgpack_fuzzer.cpp
Normal file
11
fuzzing/msgpack_fuzzer.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc;
|
||||
DeserializationError error = deserializeMsgPack(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeMsgPack(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
fuzzing/msgpack_seed_corpus/array16
Normal file
BIN
fuzzing/msgpack_seed_corpus/array16
Normal file
Binary file not shown.
BIN
fuzzing/msgpack_seed_corpus/array32
Normal file
BIN
fuzzing/msgpack_seed_corpus/array32
Normal file
Binary file not shown.
1
fuzzing/msgpack_seed_corpus/false
Normal file
1
fuzzing/msgpack_seed_corpus/false
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/fixarray
Normal file
1
fuzzing/msgpack_seed_corpus/fixarray
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>hello<EFBFBD>world
|
1
fuzzing/msgpack_seed_corpus/fixint_negative
Normal file
1
fuzzing/msgpack_seed_corpus/fixint_negative
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/fixint_positive
Normal file
1
fuzzing/msgpack_seed_corpus/fixint_positive
Normal file
@ -0,0 +1 @@
|
||||
|
1
fuzzing/msgpack_seed_corpus/fixmap
Normal file
1
fuzzing/msgpack_seed_corpus/fixmap
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>one<01>two
|
1
fuzzing/msgpack_seed_corpus/fixstr
Normal file
1
fuzzing/msgpack_seed_corpus/fixstr
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>hello world
|
1
fuzzing/msgpack_seed_corpus/float32
Normal file
1
fuzzing/msgpack_seed_corpus/float32
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>@H<><48>
|
1
fuzzing/msgpack_seed_corpus/float64
Normal file
1
fuzzing/msgpack_seed_corpus/float64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>@ !<21><><EFBFBD>o
|
1
fuzzing/msgpack_seed_corpus/int16
Normal file
1
fuzzing/msgpack_seed_corpus/int16
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/int32
Normal file
1
fuzzing/msgpack_seed_corpus/int32
Normal file
@ -0,0 +1 @@
|
||||
Ҷi<EFBFBD>.
|
1
fuzzing/msgpack_seed_corpus/int64
Normal file
1
fuzzing/msgpack_seed_corpus/int64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/int8
Normal file
1
fuzzing/msgpack_seed_corpus/int8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>
|
BIN
fuzzing/msgpack_seed_corpus/map16
Normal file
BIN
fuzzing/msgpack_seed_corpus/map16
Normal file
Binary file not shown.
BIN
fuzzing/msgpack_seed_corpus/map32
Normal file
BIN
fuzzing/msgpack_seed_corpus/map32
Normal file
Binary file not shown.
1
fuzzing/msgpack_seed_corpus/nil
Normal file
1
fuzzing/msgpack_seed_corpus/nil
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
BIN
fuzzing/msgpack_seed_corpus/str16
Normal file
BIN
fuzzing/msgpack_seed_corpus/str16
Normal file
Binary file not shown.
BIN
fuzzing/msgpack_seed_corpus/str32
Normal file
BIN
fuzzing/msgpack_seed_corpus/str32
Normal file
Binary file not shown.
1
fuzzing/msgpack_seed_corpus/str8
Normal file
1
fuzzing/msgpack_seed_corpus/str8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>hello
|
1
fuzzing/msgpack_seed_corpus/true
Normal file
1
fuzzing/msgpack_seed_corpus/true
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/uint16
Normal file
1
fuzzing/msgpack_seed_corpus/uint16
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>09
|
1
fuzzing/msgpack_seed_corpus/uint32
Normal file
1
fuzzing/msgpack_seed_corpus/uint32
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx
|
1
fuzzing/msgpack_seed_corpus/uint64
Normal file
1
fuzzing/msgpack_seed_corpus/uint64
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
1
fuzzing/msgpack_seed_corpus/uint8
Normal file
1
fuzzing/msgpack_seed_corpus/uint8
Normal file
@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>
|
26
keywords.txt
26
keywords.txt
@ -1,15 +1,17 @@
|
||||
add KEYWORD2
|
||||
as KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
createNestedObject KEYWORD2
|
||||
deserializeJson KEYWORD2
|
||||
deserializeMsgPack KEYWORD2
|
||||
DynamicJsonDocument KEYWORD1
|
||||
get KEYWORD2
|
||||
JsonArray KEYWORD1
|
||||
JsonObject KEYWORD1
|
||||
JsonVariant KEYWORD1
|
||||
StaticJsonBuffer KEYWORD1
|
||||
DynamicJsonBuffer KEYWORD1
|
||||
add KEYWORD2
|
||||
createArray KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
createNestedObject KEYWORD2
|
||||
createObject KEYWORD2
|
||||
parseArray KEYWORD2
|
||||
parseObject KEYWORD2
|
||||
prettyPrintTo KEYWORD2
|
||||
printTo KEYWORD2
|
||||
success KEYWORD2
|
||||
serializeMsgPack KEYWORD2
|
||||
serializeJson KEYWORD2
|
||||
serializeJsonPretty KEYWORD2
|
||||
set KEYWORD2
|
||||
StaticJsonDocument KEYWORD1
|
||||
to KEYWORD2
|
||||
|
@ -2,11 +2,12 @@
|
||||
"name": "ArduinoJson",
|
||||
"keywords": "json, rest, http, web",
|
||||
"description": "An elegant and efficient JSON library for embedded systems",
|
||||
"homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "5.12.0",
|
||||
"version": "6.0.0-beta",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=ArduinoJson
|
||||
version=5.12.0
|
||||
version=6.0.0-beta
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||
category=Data Processing
|
||||
url=https://arduinojson.org/
|
||||
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
||||
architectures=*
|
||||
repository=https://github.com/bblanchon/ArduinoJson.git
|
||||
license=MIT
|
||||
|
11
scripts/oss-fuzz/Vagrantfile
vendored
11
scripts/oss-fuzz/Vagrantfile
vendored
@ -2,11 +2,16 @@
|
||||
Vagrant.configure(2) do |config|
|
||||
config.vm.box = "ubuntu/xenial64"
|
||||
|
||||
config.vm.synced_folder "E:\\Git\\Arduino\\libraries\\ArduinoJson", "/host/ArduinoJson"
|
||||
config.vm.synced_folder "../..", "/host/ArduinoJson"
|
||||
config.vm.synced_folder "E:\\Git\\oss-fuzz", "/host/oss-fuzz"
|
||||
|
||||
config.vm.network "forwarded_port", guest: 8001, host: 8001
|
||||
|
||||
config.vm.provider "virtualbox" do |v|
|
||||
v.memory = 2048
|
||||
v.cpus = 2
|
||||
end
|
||||
|
||||
config.vm.provision "shell", privileged: false, inline: <<-SHELL
|
||||
set -x
|
||||
|
||||
@ -18,10 +23,6 @@ Vagrant.configure(2) do |config|
|
||||
git clone https://github.com/google/fuzzer-test-suite.git FTS
|
||||
./FTS/tutorial/install-deps.sh # Get deps
|
||||
./FTS/tutorial/install-clang.sh # Get fresh clang binaries
|
||||
# Get libFuzzer sources and build it
|
||||
svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
|
||||
Fuzzer/build.sh
|
||||
sudo mv libFuzzer.a /usr/local/lib/
|
||||
|
||||
echo "export PROJECT_NAME='arduinojson'" >> $HOME/.profile
|
||||
echo "export CC='clang'" >> $HOME/.profile
|
||||
|
26
scripts/travis/fuzz.sh
Executable file
26
scripts/travis/fuzz.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=${ROOT_DIR}/src/
|
||||
FUZZING_DIR=${ROOT_DIR}/fuzzing/
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
|
||||
|
||||
fuzz() {
|
||||
NAME="$1"
|
||||
FUZZER="${NAME}_fuzzer"
|
||||
FUZZER_CPP="${FUZZING_DIR}/${NAME}_fuzzer.cpp"
|
||||
CORPUS_DIR="${FUZZING_DIR}/${NAME}_corpus"
|
||||
SEED_CORPUS_DIR="${FUZZING_DIR}/${NAME}_seed_corpus"
|
||||
|
||||
clang++-${CLANG} ${CXXFLAGS} -o ${FUZZER} -I$INCLUDE_DIR ${FUZZER_CPP}
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30
|
||||
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
}
|
||||
|
||||
fuzz json
|
||||
fuzz msgpack
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,17 +1,19 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
#include "ArduinoJson/version.hpp"
|
||||
|
||||
#include "ArduinoJson/DynamicJsonDocument.hpp"
|
||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
||||
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
||||
#include "ArduinoJson/StaticJsonDocument.hpp"
|
||||
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonBufferImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@ -130,11 +130,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Enable deprecated functions by default
|
||||
#ifndef ARDUINOJSON_ENABLE_DEPRECATED
|
||||
#define ARDUINOJSON_ENABLE_DEPRECATED 1
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for big numbers
|
||||
// CAUTION: cannot be more that 1e9 !!!!
|
||||
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
|
||||
@ -149,3 +144,13 @@
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_LITTLE_ENDIAN
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
(defined(__LITTLE_ENDIAN__))
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
#endif
|
||||
|
17
src/ArduinoJson/Data/IsVariant.hpp
Normal file
17
src/ArduinoJson/Data/IsVariant.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class JsonVariantTag {};
|
||||
|
||||
template <typename T>
|
||||
struct IsVariant : is_base_of<JsonVariantTag, T> {};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,10 +1,10 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListIterator.hpp"
|
||||
|
||||
@ -27,7 +27,7 @@ class List {
|
||||
// When buffer is NULL, the List is not able to grow and success() returns
|
||||
// false. This is used to identify bad memory allocations and parsing
|
||||
// failures.
|
||||
explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {}
|
||||
explicit List(JsonBuffer *buf) : _buffer(buf), _firstNode(NULL) {}
|
||||
|
||||
// Returns true if the object is valid
|
||||
// Would return false in the following situation:
|
||||
@ -84,11 +84,19 @@ class List {
|
||||
}
|
||||
}
|
||||
|
||||
JsonBuffer &buffer() const {
|
||||
return *_buffer;
|
||||
}
|
||||
|
||||
protected:
|
||||
void clear() {
|
||||
_firstNode = 0;
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,12 +1,12 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for NULL
|
||||
|
||||
#include "JsonBufferAllocated.hpp"
|
||||
#include "../Memory/JsonBufferAllocated.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
@ -20,5 +20,5 @@ struct ListNode : public Internals::JsonBufferAllocated {
|
||||
ListNode<T> *next;
|
||||
T content;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "../Strings/StringTraits.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Source, typename Enable = void>
|
||||
struct ValueSaver {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
struct ValueSaver<
|
||||
Source, typename enable_if<StringTraits<Source>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
|
||||
if (!StringTraits<Source>::is_null(source)) {
|
||||
typename StringTraits<Source>::duplicate_t dup =
|
||||
StringTraits<Source>::duplicate(source, buffer);
|
||||
if (!dup) return false;
|
||||
dest = dup;
|
||||
} else {
|
||||
dest = reinterpret_cast<const char*>(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// const char*, const signed char*, const unsigned char*
|
||||
template <typename Char>
|
||||
struct ValueSaver<
|
||||
Char*, typename enable_if<!StringTraits<Char*>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& dest, Char* source) {
|
||||
dest = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,48 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TSourceRef, typename Enable = void>
|
||||
struct ValueSetter {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TSourceRef>
|
||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<StringTraits<
|
||||
TSourceRef>::should_duplicate>::type> {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer* buffer, TDestination& destination,
|
||||
TSourceRef source) {
|
||||
const char* copy = buffer->strdup(source);
|
||||
if (!copy) return false;
|
||||
destination = copy;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TSourceRef>
|
||||
struct ValueSetter<TSourceRef, typename TypeTraits::EnableIf<!StringTraits<
|
||||
TSourceRef>::should_duplicate>::type> {
|
||||
template <typename TDestination>
|
||||
static bool set(JsonBuffer*, TDestination& destination, TSourceRef source) {
|
||||
// unsigned char* -> char*
|
||||
destination = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
41
src/ArduinoJson/Deserialization/ArduinoStreamReader.hpp
Normal file
41
src/ArduinoJson/Deserialization/ArduinoStreamReader.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
struct ArduinoStreamReader {
|
||||
Stream& _stream;
|
||||
char _current;
|
||||
bool _ended;
|
||||
|
||||
public:
|
||||
explicit ArduinoStreamReader(Stream& stream)
|
||||
: _stream(stream), _current(0), _ended(false) {}
|
||||
|
||||
char read() {
|
||||
// don't use _stream.read() as it ignores the timeout
|
||||
char c = 0;
|
||||
_ended = _stream.readBytes(&c, 1) == 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ended;
|
||||
}
|
||||
};
|
||||
|
||||
inline ArduinoStreamReader makeReader(Stream& input) {
|
||||
return ArduinoStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#endif
|
64
src/ArduinoJson/Deserialization/CharPointerReader.hpp
Normal file
64
src/ArduinoJson/Deserialization/CharPointerReader.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TChar>
|
||||
class UnsafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeCharPointerReader(const TChar* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// we cannot know
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
class SafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
const TChar* _end;
|
||||
|
||||
public:
|
||||
explicit SafeCharPointerReader(const TChar* ptr, size_t len)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")),
|
||||
_end(_ptr + len) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline UnsafeCharPointerReader<TChar> makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader<TChar>(input);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline SafeCharPointerReader<TChar> makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader<TChar>(input, n);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
inline SafeCharPointerReader<char> makeReader(const String& input) {
|
||||
return SafeCharPointerReader<char>(input.c_str(), input.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,61 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
// no need to skip '*'
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '*' && input.next() == '/') {
|
||||
input.move(); // skip '*'
|
||||
input.move(); // skip '/'
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// C++-style line comment
|
||||
case '/':
|
||||
// not need to skip "//"
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
83
src/ArduinoJson/Deserialization/DeserializationError.hpp
Normal file
83
src/ArduinoJson/Deserialization/DeserializationError.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class DeserializationError {
|
||||
public:
|
||||
enum Code {
|
||||
Ok,
|
||||
IncompleteInput,
|
||||
InvalidInput,
|
||||
NoMemory,
|
||||
NotSupported,
|
||||
TooDeep
|
||||
};
|
||||
|
||||
DeserializationError() {}
|
||||
DeserializationError(Code code) : _code(code) {}
|
||||
|
||||
friend bool operator==(const DeserializationError& err, Code code) {
|
||||
return err._code == code;
|
||||
}
|
||||
|
||||
friend bool operator==(Code code, const DeserializationError& err) {
|
||||
return err._code == code;
|
||||
}
|
||||
|
||||
friend bool operator!=(const DeserializationError& err, Code code) {
|
||||
return err._code != code;
|
||||
}
|
||||
|
||||
friend bool operator!=(Code code, const DeserializationError& err) {
|
||||
return err._code != code;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return _code != Ok;
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
switch (_code) {
|
||||
case Ok:
|
||||
return "Ok";
|
||||
case TooDeep:
|
||||
return "TooDeep";
|
||||
case NoMemory:
|
||||
return "NoMemory";
|
||||
case InvalidInput:
|
||||
return "InvalidInput";
|
||||
case IncompleteInput:
|
||||
return "IncompleteInput";
|
||||
case NotSupported:
|
||||
return "NotSupported";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Code _code;
|
||||
};
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& s,
|
||||
const DeserializationError& e) {
|
||||
s << e.c_str();
|
||||
return s;
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
|
||||
s << DeserializationError(c).c_str();
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
56
src/ArduinoJson/Deserialization/FlashStringReader.hpp
Normal file
56
src/ArduinoJson/Deserialization/FlashStringReader.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
class UnsafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// this reader cannot detect the end
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class SafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
const char* _end;
|
||||
|
||||
public:
|
||||
explicit SafeFlashStringReader(const __FlashStringHelper* ptr, size_t size)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
};
|
||||
|
||||
inline UnsafeFlashStringReader makeReader(const __FlashStringHelper* input) {
|
||||
return UnsafeFlashStringReader(input);
|
||||
}
|
||||
|
||||
inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
|
||||
size_t size) {
|
||||
return SafeFlashStringReader(input, size);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#endif
|
34
src/ArduinoJson/Deserialization/IteratorReader.hpp
Normal file
34
src/ArduinoJson/Deserialization/IteratorReader.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TIterator>
|
||||
class IteratorReader {
|
||||
TIterator _ptr, _end;
|
||||
|
||||
public:
|
||||
explicit IteratorReader(TIterator begin, TIterator end)
|
||||
: _ptr(begin), _end(end) {}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
|
||||
char read() {
|
||||
return char(*_ptr++);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TInput>
|
||||
inline IteratorReader<typename TInput::const_iterator> makeReader(
|
||||
const TInput& input) {
|
||||
return IteratorReader<typename TInput::const_iterator>(input.begin(),
|
||||
input.end());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,104 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../TypeTraits/IsConst.hpp"
|
||||
#include "StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Parse JSON string to create JsonArrays and JsonObjects
|
||||
// This internal class is not indended to be used directly.
|
||||
// Instead, use JsonBuffer.parseArray() or .parseObject()
|
||||
template <typename TReader, typename TWriter>
|
||||
class JsonParser {
|
||||
public:
|
||||
JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_writer(writer),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
JsonVariant parseVariant() {
|
||||
JsonVariant result;
|
||||
parseAnythingTo(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonParser &operator=(const JsonParser &); // non-copiable
|
||||
|
||||
static bool eat(TReader &, char charToSkip);
|
||||
FORCE_INLINE bool eat(char charToSkip) {
|
||||
return eat(_reader, charToSkip);
|
||||
}
|
||||
|
||||
const char *parseString();
|
||||
bool parseAnythingTo(JsonVariant *destination);
|
||||
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
static inline bool isInRange(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool isLetterOrNumber(char c) {
|
||||
return isInRange(c, '0', '9') || isInRange(c, 'a', 'z') ||
|
||||
isInRange(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
return c == '\'' || c == '\"';
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TWriter _writer;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString, typename Enable = void>
|
||||
struct JsonParserBuilder {
|
||||
typedef typename Internals::StringTraits<TString>::Reader InputReader;
|
||||
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct JsonParserBuilder<
|
||||
TJsonBuffer, TChar *,
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsConst<TChar>::value>::type> {
|
||||
typedef typename Internals::StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef JsonParser<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
||||
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
|
||||
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
|
||||
nestingLimit);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Comments.hpp"
|
||||
#include "JsonParser.hpp"
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
|
||||
TReader &reader, char charToSkip) {
|
||||
skipSpacesAndComments(reader);
|
||||
if (reader.current() != charToSkip) return false;
|
||||
reader.move();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
|
||||
JsonVariant *destination) {
|
||||
if (_nestingLimit == 0) return false;
|
||||
_nestingLimit--;
|
||||
bool success = parseAnythingToUnsafe(destination);
|
||||
_nestingLimit++;
|
||||
return success;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingToUnsafe(
|
||||
JsonVariant *destination) {
|
||||
skipSpacesAndComments(_reader);
|
||||
|
||||
switch (_reader.current()) {
|
||||
case '[':
|
||||
return parseArrayTo(destination);
|
||||
|
||||
case '{':
|
||||
return parseObjectTo(destination);
|
||||
|
||||
default:
|
||||
return parseStringTo(destination);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonArray &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
|
||||
// Create an empty array
|
||||
JsonArray &array = _buffer->createArray();
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) goto ERROR_MISSING_BRACKET;
|
||||
if (eat(']')) goto SUCCESS_EMPTY_ARRAY;
|
||||
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// 1 - Parse value
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!array.add(value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 2 - More values?
|
||||
if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY;
|
||||
if (!eat(',')) goto ERROR_MISSING_COMMA;
|
||||
}
|
||||
|
||||
SUCCESS_EMPTY_ARRAY:
|
||||
SUCCES_NON_EMPTY_ARRAY:
|
||||
return array;
|
||||
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACKET:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArrayTo(
|
||||
JsonVariant *destination) {
|
||||
JsonArray &array = parseArray();
|
||||
if (!array.success()) return false;
|
||||
|
||||
*destination = array;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline ArduinoJson::JsonObject &
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
|
||||
// Create an empty object
|
||||
JsonObject &object = _buffer->createObject();
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) goto ERROR_MISSING_BRACE;
|
||||
if (eat('}')) goto SUCCESS_EMPTY_OBJECT;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// 1 - Parse key
|
||||
const char *key = parseString();
|
||||
if (!key) goto ERROR_INVALID_KEY;
|
||||
if (!eat(':')) goto ERROR_MISSING_COLON;
|
||||
|
||||
// 2 - Parse value
|
||||
JsonVariant value;
|
||||
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
|
||||
if (!object.set(key, value)) goto ERROR_NO_MEMORY;
|
||||
|
||||
// 3 - More keys/values?
|
||||
if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT;
|
||||
if (!eat(',')) goto ERROR_MISSING_COMMA;
|
||||
}
|
||||
|
||||
SUCCESS_EMPTY_OBJECT:
|
||||
SUCCESS_NON_EMPTY_OBJECT:
|
||||
return object;
|
||||
|
||||
ERROR_INVALID_KEY:
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACE:
|
||||
ERROR_MISSING_COLON:
|
||||
ERROR_MISSING_COMMA:
|
||||
ERROR_NO_MEMORY:
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObjectTo(
|
||||
JsonVariant *destination) {
|
||||
JsonObject &object = parseObject();
|
||||
if (!object.success()) return false;
|
||||
|
||||
*destination = object;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline const char *
|
||||
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
|
||||
typename TypeTraits::RemoveReference<TWriter>::type::String str =
|
||||
_writer.startString();
|
||||
|
||||
skipSpacesAndComments(_reader);
|
||||
char c = _reader.current();
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
_reader.move();
|
||||
char stopChar = c;
|
||||
for (;;) {
|
||||
c = _reader.current();
|
||||
if (c == '\0') break;
|
||||
_reader.move();
|
||||
|
||||
if (c == stopChar) break;
|
||||
|
||||
if (c == '\\') {
|
||||
// replace char
|
||||
c = Encoding::unescapeChar(_reader.current());
|
||||
if (c == '\0') break;
|
||||
_reader.move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
}
|
||||
} else { // no quotes
|
||||
for (;;) {
|
||||
if (!isLetterOrNumber(c)) break;
|
||||
_reader.move();
|
||||
str.append(c);
|
||||
c = _reader.current();
|
||||
}
|
||||
}
|
||||
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
template <typename TReader, typename TWriter>
|
||||
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseStringTo(
|
||||
JsonVariant *destination) {
|
||||
bool hasQuotes = isQuote(_reader.current());
|
||||
const char *value = parseString();
|
||||
if (value == NULL) return false;
|
||||
if (hasQuotes) {
|
||||
*destination = value;
|
||||
} else {
|
||||
*destination = RawJson(value);
|
||||
}
|
||||
return true;
|
||||
}
|
40
src/ArduinoJson/Deserialization/StdStreamReader.hpp
Normal file
40
src/ArduinoJson/Deserialization/StdStreamReader.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
|
||||
#include <istream>
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class StdStreamReader {
|
||||
std::istream& _stream;
|
||||
char _current;
|
||||
|
||||
public:
|
||||
explicit StdStreamReader(std::istream& stream)
|
||||
: _stream(stream), _current(0) {}
|
||||
|
||||
bool ended() const {
|
||||
return _stream.eof();
|
||||
}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(_stream.get());
|
||||
}
|
||||
|
||||
private:
|
||||
StdStreamReader& operator=(const StdStreamReader&); // Visual Studio C4512
|
||||
};
|
||||
|
||||
inline StdStreamReader makeReader(std::istream& input) {
|
||||
return StdStreamReader(input);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
||||
#endif
|
82
src/ArduinoJson/Deserialization/deserialize.hpp
Normal file
82
src/ArduinoJson/Deserialization/deserialize.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../StringStorage/StringStorage.hpp"
|
||||
#include "./ArduinoStreamReader.hpp"
|
||||
#include "./CharPointerReader.hpp"
|
||||
#include "./DeserializationError.hpp"
|
||||
#include "./FlashStringReader.hpp"
|
||||
#include "./IteratorReader.hpp"
|
||||
#include "./StdStreamReader.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <template <typename, typename> class TDeserializer,
|
||||
typename TJsonBuffer, typename TReader, typename TWriter>
|
||||
TDeserializer<TReader, TWriter> makeDeserializer(TJsonBuffer *buffer,
|
||||
TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit) {
|
||||
return TDeserializer<TReader, TWriter>(buffer, reader, writer, nestingLimit);
|
||||
}
|
||||
|
||||
// DeserializationError deserialize(TDocument& doc, TString input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TString = const std::string&, const String&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TString>
|
||||
typename Internals::enable_if<!Internals::is_array<TString>::value,
|
||||
DeserializationError>::type
|
||||
deserialize(TDocument &doc, const TString &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TChar* input, size_t
|
||||
// inputSize);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TChar* = char*, const char*, const FlashStringHelper*
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TChar>
|
||||
DeserializationError deserialize(TDocument &doc, TChar *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(
|
||||
&doc.buffer(), makeReader(input, inputSize),
|
||||
makeStringStorage(doc.buffer(), input), doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
//
|
||||
// DeserializationError deserialize(TDocument& doc, TStream input);
|
||||
// TDocument = DynamicJsonDocument, StaticJsonDocument
|
||||
// TStream = std::istream&, Stream&
|
||||
template <template <typename, typename> class TDeserializer, typename TDocument,
|
||||
typename TStream>
|
||||
DeserializationError deserialize(TDocument &doc, TStream &input) {
|
||||
using namespace Internals;
|
||||
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
|
||||
makeStringStorage(doc.buffer(), input),
|
||||
doc.nestingLimit)
|
||||
.parse(doc.template to<JsonVariant>());
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
86
src/ArduinoJson/DynamicJsonDocument.hpp
Normal file
86
src/ArduinoJson/DynamicJsonDocument.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.hpp"
|
||||
#include "JsonObject.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Memory/DynamicJsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class DynamicJsonDocument {
|
||||
Internals::DynamicJsonBuffer _buffer;
|
||||
JsonVariant _root;
|
||||
|
||||
public:
|
||||
uint8_t nestingLimit;
|
||||
|
||||
DynamicJsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
DynamicJsonDocument(size_t capacity)
|
||||
: _buffer(capacity), nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return _root.is<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return _root.as<T>();
|
||||
}
|
||||
|
||||
// JsonObject& to<JsonObject>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
|
||||
JsonObject&>::type
|
||||
to() {
|
||||
clear();
|
||||
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
|
||||
if (!object) return JsonObject::invalid();
|
||||
_root = object;
|
||||
return *object;
|
||||
}
|
||||
|
||||
// JsonArray& to<JsonArray>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
|
||||
JsonArray&>::type
|
||||
to() {
|
||||
clear();
|
||||
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
|
||||
if (!array) return JsonArray::invalid();
|
||||
_root = array;
|
||||
return *array;
|
||||
}
|
||||
|
||||
// JsonVariant& to<JsonVariant>()
|
||||
template <typename T>
|
||||
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
|
||||
T&>::type
|
||||
to() {
|
||||
clear();
|
||||
return _root;
|
||||
}
|
||||
|
||||
Internals::DynamicJsonBuffer& buffer() {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_buffer.clear();
|
||||
_root = JsonVariant();
|
||||
}
|
||||
|
||||
size_t memoryUsage() const {
|
||||
return _buffer.size();
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void visit(Visitor& visitor) const {
|
||||
return _root.visit(visitor);
|
||||
}
|
||||
};
|
||||
} // namespace ArduinoJson
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@ -7,7 +7,7 @@
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class Encoding {
|
||||
class EscapeSequence {
|
||||
public:
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char escapeChar(char c) {
|
||||
@ -33,5 +33,5 @@ class Encoding {
|
||||
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@ -8,7 +8,7 @@ namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Decorator on top of Print to allow indented output.
|
||||
// This class is used by JsonPrintable::prettyPrintTo() but can also be used
|
||||
// This class is used by serializeJsonPretty() but can also be used
|
||||
// for your own purpose, like logging.
|
||||
template <typename Print>
|
||||
class IndentedPrint {
|
||||
@ -64,5 +64,5 @@ class IndentedPrint {
|
||||
static const int MAX_LEVEL = 15; // because it's only 4 bits
|
||||
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
318
src/ArduinoJson/Json/JsonDeserializer.hpp
Normal file
318
src/ArduinoJson/Json/JsonDeserializer.hpp
Normal file
@ -0,0 +1,318 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Deserialization/deserialize.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Memory/JsonBuffer.hpp"
|
||||
#include "../Polyfills/type_traits.hpp"
|
||||
#include "./EscapeSequence.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TReader, typename TStringStorage>
|
||||
class JsonDeserializer {
|
||||
public:
|
||||
JsonDeserializer(JsonBuffer *buffer, TReader reader,
|
||||
TStringStorage stringStorage, uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_stringStorage(stringStorage),
|
||||
_nestingLimit(nestingLimit),
|
||||
_loaded(false) {}
|
||||
DeserializationError parse(JsonVariant &variant) {
|
||||
DeserializationError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
switch (current()) {
|
||||
case '[':
|
||||
return parseArray(variant);
|
||||
|
||||
case '{':
|
||||
return parseObject(variant);
|
||||
|
||||
default:
|
||||
return parseValue(variant);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JsonDeserializer &operator=(const JsonDeserializer &); // non-copiable
|
||||
|
||||
char current() {
|
||||
if (!_loaded) {
|
||||
if (_reader.ended())
|
||||
_current = 0;
|
||||
else
|
||||
_current = _reader.read();
|
||||
_loaded = true;
|
||||
}
|
||||
return _current;
|
||||
}
|
||||
|
||||
void move() {
|
||||
_loaded = false;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool eat(char charToSkip) {
|
||||
if (current() != charToSkip) return false;
|
||||
move();
|
||||
return true;
|
||||
}
|
||||
|
||||
DeserializationError parseArray(JsonVariant &variant) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
JsonArray *array = new (_buffer) JsonArray(_buffer);
|
||||
if (!array) return DeserializationError::NoMemory;
|
||||
variant = array;
|
||||
|
||||
// Check opening braket
|
||||
if (!eat('[')) return DeserializationError::InvalidInput;
|
||||
|
||||
// Skip spaces
|
||||
DeserializationError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// Empty array?
|
||||
if (eat(']')) return DeserializationError::Ok;
|
||||
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// 1 - Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
if (!array->add(value)) return DeserializationError::NoMemory;
|
||||
|
||||
// 2 - Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// 3 - More values?
|
||||
if (eat(']')) return DeserializationError::Ok;
|
||||
if (!eat(',')) return DeserializationError::InvalidInput;
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseObject(JsonVariant &variant) {
|
||||
if (_nestingLimit == 0) return DeserializationError::TooDeep;
|
||||
|
||||
JsonObject *object = new (_buffer) JsonObject(_buffer);
|
||||
if (!object) return DeserializationError::NoMemory;
|
||||
variant = object;
|
||||
|
||||
// Check opening brace
|
||||
if (!eat('{')) return DeserializationError::InvalidInput;
|
||||
|
||||
// Skip spaces
|
||||
DeserializationError err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// Empty object?
|
||||
if (eat('}')) return DeserializationError::Ok;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// Parse key
|
||||
const char *key;
|
||||
err = parseString(&key);
|
||||
if (err) return err;
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// Colon
|
||||
if (!eat(':')) return DeserializationError::InvalidInput;
|
||||
|
||||
// Parse value
|
||||
JsonVariant value;
|
||||
_nestingLimit--;
|
||||
err = parse(value);
|
||||
_nestingLimit++;
|
||||
if (err) return err;
|
||||
if (!object->set(key, value)) return DeserializationError::NoMemory;
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
|
||||
// More keys/values?
|
||||
if (eat('}')) return DeserializationError::Ok;
|
||||
if (!eat(',')) return DeserializationError::InvalidInput;
|
||||
|
||||
// Skip spaces
|
||||
err = skipSpacesAndComments();
|
||||
if (err) return err;
|
||||
}
|
||||
}
|
||||
|
||||
DeserializationError parseValue(JsonVariant &variant) {
|
||||
bool hasQuotes = isQuote(current());
|
||||
const char *value;
|
||||
DeserializationError error = parseString(&value);
|
||||
if (error) return error;
|
||||
if (hasQuotes) {
|
||||
variant = value;
|
||||
} else {
|
||||
variant = RawJson(value);
|
||||
}
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
DeserializationError parseString(const char **result) {
|
||||
typename remove_reference<TStringStorage>::type::String str =
|
||||
_stringStorage.startString();
|
||||
|
||||
char c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
|
||||
if (isQuote(c)) { // quotes
|
||||
move();
|
||||
char stopChar = c;
|
||||
for (;;) {
|
||||
c = current();
|
||||
move();
|
||||
if (c == stopChar) break;
|
||||
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
|
||||
if (c == '\\') {
|
||||
c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
if (c == 'u') return DeserializationError::NotSupported;
|
||||
// replace char
|
||||
c = EscapeSequence::unescapeChar(c);
|
||||
if (c == '\0') return DeserializationError::InvalidInput;
|
||||
move();
|
||||
}
|
||||
|
||||
str.append(c);
|
||||
}
|
||||
} else if (canBeInNonQuotedString(c)) { // no quotes
|
||||
do {
|
||||
move();
|
||||
str.append(c);
|
||||
c = current();
|
||||
} while (canBeInNonQuotedString(c));
|
||||
} else {
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
*result = str.c_str();
|
||||
if (*result == NULL) return DeserializationError::NoMemory;
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
static inline bool isBetween(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool canBeInNonQuotedString(char c) {
|
||||
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
|
||||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
return c == '\'' || c == '\"';
|
||||
}
|
||||
|
||||
DeserializationError skipSpacesAndComments() {
|
||||
for (;;) {
|
||||
switch (current()) {
|
||||
// end of string
|
||||
case '\0':
|
||||
return DeserializationError::IncompleteInput;
|
||||
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
move(); // skip '/'
|
||||
switch (current()) {
|
||||
// block comment
|
||||
case '*': {
|
||||
move(); // skip '*'
|
||||
bool wasStar = false;
|
||||
for (;;) {
|
||||
char c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
if (c == '/' && wasStar) {
|
||||
move();
|
||||
break;
|
||||
}
|
||||
wasStar = c == '*';
|
||||
move();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// trailing comment
|
||||
case '/':
|
||||
// no need to skip "//"
|
||||
for (;;) {
|
||||
move();
|
||||
char c = current();
|
||||
if (c == '\0') return DeserializationError::IncompleteInput;
|
||||
if (c == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
uint8_t _nestingLimit;
|
||||
char _current;
|
||||
bool _loaded;
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput *input,
|
||||
size_t inputSize) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize);
|
||||
}
|
||||
|
||||
template <typename TDocument, typename TInput>
|
||||
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
|
||||
using namespace Internals;
|
||||
return deserialize<JsonDeserializer>(doc, input);
|
||||
}
|
||||
} // namespace ArduinoJson
|
139
src/ArduinoJson/Json/JsonSerializer.hpp
Normal file
139
src/ArduinoJson/Json/JsonSerializer.hpp
Normal file
@ -0,0 +1,139 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./JsonWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TPrint>
|
||||
class JsonSerializer {
|
||||
public:
|
||||
JsonSerializer(TPrint &destination) : _writer(destination) {}
|
||||
|
||||
void acceptFloat(JsonFloat value) {
|
||||
_writer.writeFloat(value);
|
||||
}
|
||||
|
||||
void acceptArray(const JsonArray &array) {
|
||||
_writer.beginArray();
|
||||
|
||||
JsonArray::const_iterator it = array.begin();
|
||||
while (it != array.end()) {
|
||||
it->visit(*this);
|
||||
|
||||
++it;
|
||||
if (it == array.end()) break;
|
||||
|
||||
_writer.writeComma();
|
||||
}
|
||||
|
||||
_writer.endArray();
|
||||
}
|
||||
|
||||
void acceptObject(const JsonObject &object) {
|
||||
_writer.beginObject();
|
||||
|
||||
JsonObject::const_iterator it = object.begin();
|
||||
while (it != object.end()) {
|
||||
_writer.writeString(it->key);
|
||||
_writer.writeColon();
|
||||
it->value.visit(*this);
|
||||
|
||||
++it;
|
||||
if (it == object.end()) break;
|
||||
|
||||
_writer.writeComma();
|
||||
}
|
||||
|
||||
_writer.endObject();
|
||||
}
|
||||
|
||||
void acceptString(const char *value) {
|
||||
_writer.writeString(value);
|
||||
}
|
||||
|
||||
void acceptRawJson(const char *value) {
|
||||
_writer.writeRaw(value);
|
||||
}
|
||||
|
||||
void acceptNegativeInteger(JsonUInt value) {
|
||||
_writer.writeRaw('-');
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
void acceptPositiveInteger(JsonUInt value) {
|
||||
_writer.writeInteger(value);
|
||||
}
|
||||
|
||||
void acceptBoolean(bool value) {
|
||||
_writer.writeBoolean(value);
|
||||
}
|
||||
|
||||
void acceptUndefined() {}
|
||||
|
||||
size_t bytesWritten() const {
|
||||
return _writer.bytesWritten();
|
||||
}
|
||||
|
||||
private:
|
||||
JsonWriter<TPrint> _writer;
|
||||
};
|
||||
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJson(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
return serialize<JsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
|
||||
using namespace Internals;
|
||||
return serialize<JsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJson(const TSource &source) {
|
||||
using namespace Internals;
|
||||
return measure<JsonSerializer>(source);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonObject &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
namespace Internals {
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const JsonArraySubscript &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline std::ostream &operator<<(std::ostream &os,
|
||||
const JsonObjectSubscript<TKey> &source) {
|
||||
serializeJson(source, os);
|
||||
return os;
|
||||
}
|
||||
} // namespace Internals
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,14 +1,14 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../Data/Encoding.hpp"
|
||||
#include "../Data/JsonInteger.hpp"
|
||||
#include "../Numbers/FloatParts.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "../Serialization/FloatParts.hpp"
|
||||
#include "./EscapeSequence.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
@ -26,8 +26,6 @@ class JsonWriter {
|
||||
explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {}
|
||||
|
||||
// Returns the number of bytes sent to the Print implementation.
|
||||
// This is very handy for implementations of printTo() that must return the
|
||||
// number of bytes written.
|
||||
size_t bytesWritten() const {
|
||||
return _length;
|
||||
}
|
||||
@ -68,7 +66,7 @@ class JsonWriter {
|
||||
}
|
||||
|
||||
void writeChar(char c) {
|
||||
char specialChar = Encoding::escapeChar(c);
|
||||
char specialChar = EscapeSequence::escapeChar(c);
|
||||
if (specialChar) {
|
||||
writeRaw('\\');
|
||||
writeRaw(specialChar);
|
||||
@ -79,14 +77,14 @@ class JsonWriter {
|
||||
|
||||
template <typename TFloat>
|
||||
void writeFloat(TFloat value) {
|
||||
if (Polyfills::isNaN(value)) return writeRaw("NaN");
|
||||
if (isnan(value)) return writeRaw("NaN");
|
||||
|
||||
if (value < 0.0) {
|
||||
writeRaw('-');
|
||||
value = -value;
|
||||
}
|
||||
|
||||
if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
|
||||
if (isinf(value)) return writeRaw("Infinity");
|
||||
|
||||
FloatParts<TFloat> parts(value);
|
||||
|
||||
@ -151,5 +149,5 @@ class JsonWriter {
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
57
src/ArduinoJson/Json/PrettyJsonSerializer.hpp
Normal file
57
src/ArduinoJson/Json/PrettyJsonSerializer.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Serialization/measure.hpp"
|
||||
#include "../Serialization/serialize.hpp"
|
||||
#include "./IndentedPrint.hpp"
|
||||
#include "./JsonSerializer.hpp"
|
||||
#include "./Prettyfier.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TPrint>
|
||||
class PrettyJsonSerializer_Base {
|
||||
public:
|
||||
PrettyJsonSerializer_Base(TPrint &output)
|
||||
: _indentedPrint(output), _prettyfier(_indentedPrint) {}
|
||||
|
||||
protected:
|
||||
IndentedPrint<TPrint> _indentedPrint;
|
||||
Prettyfier<TPrint> _prettyfier;
|
||||
};
|
||||
|
||||
template <typename TPrint>
|
||||
class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
|
||||
public JsonSerializer<Prettyfier<TPrint> > {
|
||||
public:
|
||||
PrettyJsonSerializer(TPrint &output)
|
||||
: PrettyJsonSerializer_Base<TPrint>(output),
|
||||
JsonSerializer<Prettyfier<TPrint> >(
|
||||
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
|
||||
};
|
||||
} // namespace Internals
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
|
||||
using namespace Internals;
|
||||
return serialize<PrettyJsonSerializer>(source, destination);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t serializeJsonPretty(const TSource &source, char *buffer,
|
||||
size_t bufferSize) {
|
||||
using namespace Internals;
|
||||
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
|
||||
}
|
||||
|
||||
template <typename TSource>
|
||||
size_t measureJsonPretty(const TSource &source) {
|
||||
using namespace Internals;
|
||||
return measure<PrettyJsonSerializer>(source);
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
@ -1,20 +1,16 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonBufferAllocated.hpp"
|
||||
#include "Data/List.hpp"
|
||||
#include "Data/ReferenceType.hpp"
|
||||
#include "Data/ValueSetter.hpp"
|
||||
#include "Data/ValueSaver.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsArray.hpp"
|
||||
#include "TypeTraits/IsFloatingPoint.hpp"
|
||||
#include "TypeTraits/IsSame.hpp"
|
||||
#include "Memory/JsonBufferAllocated.hpp"
|
||||
#include "Polyfills/type_traits.hpp"
|
||||
#include "Strings/StringTraits.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
@ -26,49 +22,39 @@ namespace ArduinoJson {
|
||||
// Forward declarations
|
||||
class JsonObject;
|
||||
class JsonBuffer;
|
||||
namespace Internals {
|
||||
class JsonArraySubscript;
|
||||
}
|
||||
|
||||
// An array of JsonVariant.
|
||||
//
|
||||
// The constructor is private, instances must be created via
|
||||
// JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
// A JsonArray can be serialized to a JSON string via JsonArray::printTo().
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseArray().
|
||||
class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
public Internals::ReferenceType,
|
||||
class JsonArray : public Internals::ReferenceType,
|
||||
public Internals::NonCopyable,
|
||||
public Internals::List<JsonVariant>,
|
||||
public Internals::JsonBufferAllocated {
|
||||
public:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
// You should not call this constructor directly.
|
||||
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
|
||||
explicit JsonArray(JsonBuffer *buffer) throw()
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
explicit JsonArray(Internals::JsonBuffer *buf) throw()
|
||||
: Internals::List<JsonVariant>(buf) {}
|
||||
|
||||
// Gets the value at the specified index
|
||||
const JsonArraySubscript operator[](size_t index) const;
|
||||
const Internals::JsonArraySubscript operator[](size_t index) const;
|
||||
|
||||
// Gets or sets the value at specified index
|
||||
JsonArraySubscript operator[](size_t index);
|
||||
Internals::JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type add(
|
||||
const T &value) {
|
||||
bool add(const T &value) {
|
||||
return add_impl<const T &>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue);
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool add(const T *value) {
|
||||
return add_impl<const T *>(value);
|
||||
bool add(T *value) {
|
||||
return add_impl<T *>(value);
|
||||
}
|
||||
//
|
||||
// bool add(TValue value, uint8_t decimals);
|
||||
@ -81,27 +67,25 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
|
||||
// Sets the value at specified index.
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// bool add(size_t index, const TValue&);
|
||||
// TValue = bool, long, int, short, float, double, RawJson, JsonVariant,
|
||||
// const std::string&, const String&,
|
||||
// const JsonArray&, const JsonObject&
|
||||
// std::string, String, JsonArray, JsonObject
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsArray<T>::value, bool>::type set(
|
||||
size_t index, const T &value) {
|
||||
bool set(size_t index, const T &value) {
|
||||
return set_impl<const T &>(index, value);
|
||||
}
|
||||
//
|
||||
// bool add(size_t index, TValue);
|
||||
// TValue = const char*, const char[N], const FlashStringHelper*
|
||||
// TValue = char*, const char*, const FlashStringHelper*
|
||||
template <typename T>
|
||||
bool set(size_t index, const T *value) {
|
||||
return set_impl<const T *>(index, value);
|
||||
bool set(size_t index, T *value) {
|
||||
return set_impl<T *>(index, value);
|
||||
}
|
||||
//
|
||||
// bool set(size_t index, TValue value, uint8_t decimals);
|
||||
// TValue = float, double
|
||||
template <typename T>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||
typename Internals::enable_if<Internals::is_floating_point<T>::value,
|
||||
bool>::type
|
||||
set(size_t index, T value, uint8_t decimals) {
|
||||
return set_impl<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
@ -122,11 +106,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
}
|
||||
|
||||
// Creates a JsonArray and adds a reference at the end of the array.
|
||||
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
|
||||
JsonArray &createNestedArray();
|
||||
|
||||
// Creates a JsonObject and adds a reference at the end of the array.
|
||||
// It's a shortcut for JsonBuffer::createObject() and JsonArray::add()
|
||||
JsonObject &createNestedObject();
|
||||
|
||||
// Removes element at specified index.
|
||||
@ -196,26 +178,24 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
}
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_DEPRECATED
|
||||
DEPRECATED("use remove() instead")
|
||||
FORCE_INLINE void removeAt(size_t index) {
|
||||
return remove(index);
|
||||
template <typename Visitor>
|
||||
void visit(Visitor &visitor) const {
|
||||
return visitor.acceptArray(*this);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
template <typename TValueRef>
|
||||
bool set_impl(size_t index, TValueRef value) {
|
||||
iterator it = begin() += index;
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value);
|
||||
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||
}
|
||||
|
||||
template <typename TValueRef>
|
||||
bool add_impl(TValueRef value) {
|
||||
iterator it = Internals::List<JsonVariant>::add();
|
||||
if (it == end()) return false;
|
||||
return Internals::ValueSetter<TValueRef>::set(_buffer, *it, value);
|
||||
return Internals::ValueSaver<TValueRef>::save(_buffer, *it, value);
|
||||
}
|
||||
};
|
||||
|
||||
@ -226,5 +206,5 @@ struct JsonVariantDefault<JsonArray> {
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
@ -11,16 +11,18 @@
|
||||
namespace ArduinoJson {
|
||||
|
||||
inline JsonArray &JsonArray::createNestedArray() {
|
||||
if (!_buffer) return JsonArray::invalid();
|
||||
JsonArray &array = _buffer->createArray();
|
||||
JsonArray *array = new (_buffer) JsonArray(_buffer);
|
||||
if (!array) return JsonArray::invalid();
|
||||
|
||||
add(array);
|
||||
return array;
|
||||
return *array;
|
||||
}
|
||||
|
||||
inline JsonObject &JsonArray::createNestedObject() {
|
||||
if (!_buffer) return JsonObject::invalid();
|
||||
JsonObject &object = _buffer->createObject();
|
||||
JsonObject *object = new (_buffer) JsonObject(_buffer);
|
||||
if (!object) return JsonObject::invalid();
|
||||
|
||||
add(object);
|
||||
return object;
|
||||
}
|
||||
return *object;
|
||||
}
|
||||
} // namespace ArduinoJson
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user