forked from bblanchon/ArduinoJson
Compare commits
603 Commits
Author | SHA1 | Date | |
---|---|---|---|
348357eb04 | |||
69f6967ad4 | |||
4e3f554b68 | |||
79f6f0dd86 | |||
02f6fab025 | |||
a61fc5b836 | |||
f3a84857d9 | |||
95eb16233c | |||
33654a480b | |||
c296f27640 | |||
4f55f63a77 | |||
a66299a936 | |||
a2cbb68a40 | |||
4163debdd9 | |||
c92ff81ddd | |||
783add8357 | |||
3b77dbbed7 | |||
160ff0961e | |||
06909c451f | |||
b7d8b45e5a | |||
88bfaac7e6 | |||
3c51017e4a | |||
33f6376122 | |||
2beb87136b | |||
f6f8a63b99 | |||
e0ce711eb4 | |||
0911d8d796 | |||
99e5ff78f3 | |||
5236de1433 | |||
0c9451fd5f | |||
dfac1cf71a | |||
1e20e6ef77 | |||
a7b366e74f | |||
3cfd36a5ce | |||
3919f07890 | |||
12e374d0da | |||
36ee4876c6 | |||
05db56760f | |||
e94089ca56 | |||
dc1d0ca698 | |||
627d85ce23 | |||
f6133f2d36 | |||
d8dbfe6e6d | |||
1c450fd3aa | |||
2e47d546b2 | |||
01f13c1b11 | |||
9dc7c2a031 | |||
fe779dace4 | |||
6eef52cc9c | |||
d38131d495 | |||
b4b475d692 | |||
fe17706b6c | |||
d7bad3d70b | |||
5a56ec0636 | |||
35a95f00d9 | |||
93397880ca | |||
8c4c3d8fda | |||
49025d322f | |||
9d2ee6ce63 | |||
70aabca0f7 | |||
dfd59f644b | |||
ee520d1ff5 | |||
ee580f1968 | |||
5179aa0d4f | |||
a7b78fadb0 | |||
d94bcbf249 | |||
086e99efb4 | |||
7b8aba46cc | |||
579c9359df | |||
885e35e892 | |||
e7864c9566 | |||
6e67bc442f | |||
ac9b776aa1 | |||
d8e595907b | |||
1e02fabdec | |||
79bfe731af | |||
a3425a6306 | |||
2e4dd2d591 | |||
f360cc664c | |||
ce6f839153 | |||
01949f7da0 | |||
08de76e2ba | |||
cb97e1fa19 | |||
95e564bfb6 | |||
342b079133 | |||
8138c64116 | |||
64b4e15ce6 | |||
e722fc50b1 | |||
a9f4f611d4 | |||
0fb4fa8f86 | |||
7d73e63c78 | |||
ebb591ef28 | |||
31dea656d5 | |||
768312e870 | |||
5d0e326bfd | |||
8ac4346fd5 | |||
bafec6f1a3 | |||
c6d11294e4 | |||
6ce2497879 | |||
782b178f4e | |||
64529bb1a3 | |||
01dc0d6268 | |||
289b5333d6 | |||
4a17e8c34b | |||
c4cda780d5 | |||
e5669577df | |||
97768ec176 | |||
e25eaed75a | |||
09f6d059a7 | |||
699292b058 | |||
d9cc259df3 | |||
43ad37e7ce | |||
bb816037d6 | |||
04cde11a04 | |||
2f8fde6772 | |||
f224408c07 | |||
21e073a3b4 | |||
f9ea82a2af | |||
1ce6d663af | |||
c1c63067d4 | |||
a8d3e9997e | |||
7cdf7b1769 | |||
429d5011b4 | |||
54f9bd9572 | |||
2a60c96baf | |||
f26f4263ea | |||
507f809da0 | |||
ad83820257 | |||
cd773e3f37 | |||
9da7dce310 | |||
825ab0357e | |||
fead9b50b1 | |||
98463ea168 | |||
74b4544560 | |||
2b5b8fb4c5 | |||
d35b680481 | |||
ca0fbf00f9 | |||
5443e90baf | |||
a5dbb397ca | |||
889f059758 | |||
45a8ed6531 | |||
4c204840e9 | |||
c3001e9ea9 | |||
5cf744dbac | |||
ba2b142c8a | |||
10ab95522d | |||
61218f12fd | |||
852256c1af | |||
8988cb4761 | |||
e0980292ef | |||
cdf3777aa8 | |||
618a54579f | |||
9f69fabe20 | |||
e748ce32bc | |||
fdeedabfd7 | |||
582216e004 | |||
1f6cd8e56e | |||
68fb03577c | |||
bbef8931a6 | |||
8071434515 | |||
7f22a1ab39 | |||
55b0eab3e6 | |||
e85f27c0f3 | |||
e3b4f5038d | |||
b43da1e421 | |||
5c8283b3e4 | |||
3dc533fca0 | |||
d38cbd374a | |||
9175046f35 | |||
888fdc1d54 | |||
d83f1a6319 | |||
ff5f3f3a2c | |||
e4779512e6 | |||
8947a6c9de | |||
fa805b4998 | |||
451c0ee70d | |||
40ac60b941 | |||
7e98d136f4 | |||
c800948342 | |||
7fbc3cb6a6 | |||
d842e246c9 | |||
9946abf731 | |||
1e0464f5b4 | |||
5aefc7d652 | |||
743381de6d | |||
d70ff26164 | |||
316d036785 | |||
c82e6d747b | |||
04330a7a47 | |||
cfbe50057a | |||
9c1b6b80aa | |||
0daf82eee2 | |||
074c39ca5b | |||
1abb8ac6ae | |||
b19a37538c | |||
fc4faacfec | |||
bbc2aa4f2a | |||
1f6bd5c04d | |||
32ffb75394 | |||
7df73824aa | |||
9c32ae2300 | |||
b15dac7edf | |||
2a62132bf0 | |||
a0a82c0f4e | |||
24b46af48a | |||
fed79bfd81 | |||
7dbaac1070 | |||
58d2c4a62f | |||
b847576bb4 | |||
58f155e135 | |||
241ca79114 | |||
3d92531ad3 | |||
c61ee09d26 | |||
c59ddd8a9d | |||
086d07151f | |||
a1cb9c9399 | |||
f265b6ed11 | |||
5db34580f2 | |||
beb49a9446 | |||
ee205971e9 | |||
ded6364e1d | |||
5b6b38564f | |||
31c1a3d804 | |||
81f3460806 | |||
081b345e7c | |||
f468db6757 | |||
c7dcf864cc | |||
6d39bfa703 | |||
4ee1ac015f | |||
b2e2556ef6 | |||
8f74e4e44e | |||
be891daa5a | |||
95a2d6714e | |||
3ce5e53323 | |||
f8c3cdf2ff | |||
88aed98447 | |||
3ae90b66c6 | |||
10c0a8ba70 | |||
d192a14e2e | |||
b49aa22c65 | |||
dae0dc5ebb | |||
35eaa55b3a | |||
bf2d726746 | |||
0dce0022d3 | |||
1bff34a204 | |||
24c60619d5 | |||
b0e12e8852 | |||
f7fa9e9467 | |||
09b6f71853 | |||
e28119f03b | |||
7a40711af3 | |||
b6799dc231 | |||
31c9ea9b28 | |||
6330ab1271 | |||
c35a0fadc3 | |||
bbe034222c | |||
305944e907 | |||
f0754aed53 | |||
99a785179d | |||
21259bc61a | |||
4c67d0579a | |||
cb3c59ec07 | |||
e725b756a6 | |||
dbe6f89ed8 | |||
84e34d2a27 | |||
4d2d535a03 | |||
b0e43f7538 | |||
d66a7adc22 | |||
1a98fd5dfc | |||
57400cee14 | |||
c99bdbf4b9 | |||
a665fa1dec | |||
78048d1d92 | |||
065fe57a7c | |||
f251563af1 | |||
c1ab55f9d9 | |||
27a4d57f7c | |||
22e36bbe9c | |||
d2e1b241be | |||
3d9e40a3a8 | |||
9f85368cce | |||
3243f2dc58 | |||
6b2705769a | |||
ab2587f089 | |||
d3cf568d07 | |||
e417c137fc | |||
d549070fd3 | |||
42ce5ab31f | |||
e190b20ae1 | |||
ce788d96c4 | |||
cc19266470 | |||
18f93b4eb6 | |||
e682ed5a1e | |||
bc44c36385 | |||
bcc8cece24 | |||
a7ff04db0e | |||
a9a51ec1e2 | |||
0495297c6c | |||
75588946c6 | |||
5fa446d3f5 | |||
71fd2de675 | |||
a2fc188526 | |||
166bdd6919 | |||
4d4119e589 | |||
91649df593 | |||
890e811e80 | |||
bb887f94e7 | |||
6e45f7c790 | |||
5580adb4a6 | |||
60a5d72367 | |||
4cfb0ab84d | |||
a1b6c2df75 | |||
feb6060887 | |||
49d2b4b2a2 | |||
286a514fbe | |||
9d3b522e7b | |||
c32642e130 | |||
7a3fa35bd8 | |||
0154fc15cb | |||
24d173c3b9 | |||
d4c1b6f2c2 | |||
58c051f564 | |||
763aa7fe37 | |||
cd88fb0882 | |||
ec843659d8 | |||
2997a405a0 | |||
57f28c2017 | |||
b3b70b78cf | |||
48018bd6e6 | |||
61952a9bcd | |||
602cc104f9 | |||
d71a39211d | |||
f77a8b02e3 | |||
aa2cd0db00 | |||
f127ef6019 | |||
3ae7327687 | |||
23e61cc0f7 | |||
b5002265cf | |||
e48ea94789 | |||
6539c6982c | |||
d877d77b63 | |||
1df6cde026 | |||
fafae8181b | |||
151fc52c1c | |||
ea79340dc7 | |||
9e88514700 | |||
752378a8cb | |||
8465cc0c83 | |||
2ddf8f1619 | |||
f7aa0f89e3 | |||
3d322fdb28 | |||
981adf1989 | |||
dbc3bee3a0 | |||
3f2b7b706a | |||
c243417585 | |||
514a6c0879 | |||
76f9ecce75 | |||
410ca55e88 | |||
66c05041e8 | |||
aafabd8e8d | |||
eb1a774778 | |||
75c89e7b35 | |||
e31a2136fc | |||
380722402f | |||
030c8542e7 | |||
1f25d4434e | |||
f29904e217 | |||
7246db7691 | |||
4bdbc6c1fc | |||
8e6fdb20eb | |||
016d0d699e | |||
6771603a05 | |||
d067cf0e84 | |||
13593d73a3 | |||
bc86ae800a | |||
df52dceaa1 | |||
d460b59b50 | |||
8e5ea91f8d | |||
4a8b7d0cb4 | |||
96c9b5deee | |||
8e81b9bb26 | |||
817cc09975 | |||
1bc45f1fd7 | |||
d2fe9ddf49 | |||
5cc06180e6 | |||
65e8b6d405 | |||
09294cb5e6 | |||
158f4600fb | |||
0d28612507 | |||
7c99d4d63d | |||
1a01800782 | |||
6384bc414a | |||
c10bcee324 | |||
028ff6676e | |||
23b5237f74 | |||
88510705be | |||
15d3068d78 | |||
ae6beb9340 | |||
c1f4128ccd | |||
5fb6edfc91 | |||
2771b830b7 | |||
84aa627038 | |||
4528b8fc95 | |||
60c6f2db47 | |||
13c386c7a3 | |||
7877ee1b4c | |||
2c29327ebd | |||
85ffb83aa6 | |||
1ce6661fa6 | |||
68a2ca905e | |||
7e4ab9f31c | |||
44e5549456 | |||
3e36831cdc | |||
5129f3400c | |||
0449ee4fd3 | |||
6e4eb45210 | |||
abef85218e | |||
649f292ea7 | |||
805c0741e6 | |||
0fc54ba54c | |||
df72419f09 | |||
d3d0da2d7f | |||
407d536e06 | |||
c22473cf37 | |||
3e8861b1a0 | |||
f565a9b1b7 | |||
06026cc7d4 | |||
04f52733c2 | |||
c06f42659a | |||
e619b8f5bd | |||
1e28217393 | |||
a1e8c8800a | |||
00ad540f4e | |||
cd7a7b1533 | |||
0fe77176e1 | |||
e94575b4b8 | |||
b278d7711b | |||
851d21e08c | |||
b75d32e980 | |||
daa62b3737 | |||
ed497df9d6 | |||
79953730fc | |||
5d2ffc49fd | |||
714a37bd59 | |||
4a1d8483cc | |||
0d4d77a7cd | |||
c329572d24 | |||
ca01ecfb49 | |||
78249a0ada | |||
45c9ba1191 | |||
5e1697f47b | |||
f2579397d6 | |||
b6e3a37ad9 | |||
73eda08dd4 | |||
6164328892 | |||
7487b8cbb7 | |||
6a868e46bd | |||
d189bd7140 | |||
9f07cdcabf | |||
41b5bba939 | |||
7ac4a91591 | |||
5534635feb | |||
2e5b959e8b | |||
9ee3dc638d | |||
ccb97fc6e0 | |||
39c185ae67 | |||
cf1324c09b | |||
0b087b7bdb | |||
dde5a2510b | |||
a42b03ec26 | |||
2f98e59fc6 | |||
f58a8b0ca5 | |||
4f56afe89e | |||
339de21f1c | |||
25c428c1e9 | |||
0045bb3e35 | |||
4e61a839a5 | |||
a48fbac7d7 | |||
af7dd55d34 | |||
525649c416 | |||
1f86016320 | |||
c38af3e32c | |||
0a0757945e | |||
e63cde3922 | |||
5bb6cd0fa9 | |||
bbc18b5ca4 | |||
6d3b70f4a3 | |||
cbedcdf93b | |||
6fcf9edf9a | |||
bb11fcba89 | |||
a87b2bf5bf | |||
f28997e367 | |||
42968be535 | |||
6c1ab912ff | |||
99521cc718 | |||
b3613f7137 | |||
1b62502b36 | |||
adb8fa4d44 | |||
3b6ce65054 | |||
be6c4bf4d1 | |||
4e6ad31d6a | |||
1cec019457 | |||
2e97dbdedc | |||
8f9d3b638f | |||
8be590e591 | |||
8baf21b6e8 | |||
935cb068ab | |||
efd8c0ff5c | |||
757c86ddc5 | |||
0efe8bc74a | |||
65d03c9001 | |||
df2e640b16 | |||
895482de15 | |||
477c9c2c6e | |||
50b2a1b4a7 | |||
78a920a5fc | |||
bae5c36f41 | |||
538b15b400 | |||
daba65d987 | |||
5b1c2047a4 | |||
81c7b9f700 | |||
2222714d68 | |||
dd5cf661e3 | |||
b560a87e15 | |||
4d4d775e7a | |||
9bcb5610e8 | |||
cb0973ab38 | |||
c7fb77203b | |||
e87bde6594 | |||
922b131f8d | |||
ae73a06328 | |||
61e53a505d | |||
937837848c | |||
1fba9767d3 | |||
621068260d | |||
e8831c28d9 | |||
a9b8e280fe | |||
4d5a7114c1 | |||
c3359d3eb9 | |||
c84860e3f4 | |||
1401665129 | |||
19e007c3f5 | |||
88f630cee5 | |||
a57220debc | |||
69d682ce81 | |||
81f7849c26 | |||
10068e7b22 | |||
5b2ee9ed29 | |||
93ddb9498e | |||
495efd8629 | |||
f548093d86 | |||
5f77949636 | |||
e26cea59e5 | |||
1800a8e89e | |||
1d064d709b | |||
b7933f85ba | |||
0240270492 | |||
dd8baea373 | |||
568b8988d8 | |||
4f4b35bd41 | |||
ff4060f5d1 | |||
ebb257df6e | |||
48a91a219c | |||
e75e3b6527 | |||
63ae9ef096 | |||
33508e3fe0 | |||
1c4d4bfd2d | |||
18587d132b | |||
d12e25bd8a | |||
25118ad8c0 | |||
7ab728e996 | |||
ca99749f28 | |||
55487ad668 | |||
6ea9574330 | |||
1e44f5522e | |||
786fe994aa | |||
6b61617133 | |||
45dfdbd5e4 | |||
dd6fd6f198 | |||
ca53abdc41 | |||
5e4c4a4bdc | |||
aa6cf308db | |||
b8df795cb5 | |||
4c387e9062 | |||
d57234e92c | |||
6f247a5080 | |||
d306422ed9 | |||
2a20c5a25c | |||
1118dd7b53 | |||
3d4f0f741d | |||
77a3e1737d | |||
a27bb3097a | |||
5c119099f3 | |||
bb705bab63 | |||
22ca52326c | |||
aa8cff7101 | |||
df25a21050 | |||
f18f554c2f | |||
c8c1add4ab | |||
3d8b31b1ec | |||
80e0a51c15 | |||
dd416e51f3 | |||
7059e35938 |
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
/.idea
|
||||
/build
|
||||
/bin
|
||||
/lib
|
6
.travis.yml
Normal file
6
.travis.yml
Normal file
@ -0,0 +1,6 @@
|
||||
language: c++
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
before_script: cmake .
|
||||
script: make && make test
|
105
CHANGELOG.md
105
CHANGELOG.md
@ -1,10 +1,109 @@
|
||||
ArduinoJsonParser change log
|
||||
============================
|
||||
Arduino JSON: change log
|
||||
========================
|
||||
|
||||
v4.0
|
||||
----
|
||||
|
||||
* Unified parser and generator API (issue #23)
|
||||
* Updated library layout, now requires Arduino 1.0.6 or newer
|
||||
|
||||
**BREAKING CHANGE**: API changed significantly, see `doc/Migrating to the new API.md`.
|
||||
|
||||
|
||||
v3.4
|
||||
----
|
||||
|
||||
* Fixed escaped char parsing (issue #16)
|
||||
|
||||
|
||||
v3.3
|
||||
----
|
||||
|
||||
* Added indented output for the JSON generator (issue #11), see example bellow.
|
||||
* Added `IndentedPrint`, a decorator for `Print` to allow indented output
|
||||
|
||||
Example:
|
||||
|
||||
JsonOject<2> json;
|
||||
json["key"] = "value";
|
||||
json.prettyPrintTo(Serial);
|
||||
|
||||
v3.2
|
||||
----
|
||||
|
||||
* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1).
|
||||
|
||||
v3.1
|
||||
----
|
||||
|
||||
* Calling `Generator::JsonObject::add()` twice with the same `key` now replaces the `value`
|
||||
* Added `Generator::JsonObject::operator[]`, see bellow the new API
|
||||
* Added `Generator::JsonObject::remove()` (issue #9)
|
||||
|
||||
Old generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
root.add("sensor", "gps");
|
||||
root.add("time", 1351824120);
|
||||
root.add("data", array);
|
||||
|
||||
New generator API:
|
||||
|
||||
JsonObject<3> root;
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
root["data"] = array;
|
||||
|
||||
v3.0
|
||||
----
|
||||
|
||||
* New parser API, see bellow
|
||||
* Renamed `JsonHashTable` into `JsonObject`
|
||||
* Added iterators for `JsonArray` and `JsonObject` (issue #4)
|
||||
|
||||
Old parser API:
|
||||
|
||||
JsonHashTable root = parser.parseHashTable(json);
|
||||
|
||||
char* sensor = root.getString("sensor");
|
||||
long time = root.getLong("time");
|
||||
double latitude = root.getArray("data").getDouble(0);
|
||||
double longitude = root.getArray("data").getDouble(1);
|
||||
|
||||
New parser API:
|
||||
|
||||
JsonObject root = parser.parse(json);
|
||||
|
||||
char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
v2.1
|
||||
----
|
||||
|
||||
* Fixed case `#include "jsmn.cpp"` which caused an error in Linux (issue #6)
|
||||
* Fixed a buffer overrun in JSON Parser (issue #5)
|
||||
|
||||
v2.0
|
||||
----
|
||||
|
||||
* Added JSON encoding (issue #2)
|
||||
* Renamed the library `ArduinoJsonParser` becomes `ArduinoJson`
|
||||
|
||||
**Breaking change**: you need to add the following line at the top of your program.
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
v1.2
|
||||
----
|
||||
|
||||
* Fixed error in JSON parser example (issue #1)
|
||||
|
||||
v1.1
|
||||
----
|
||||
|
||||
* Example: changed `char* json` into `char json[]` so that the byes are not write protected
|
||||
* Example: changed `char* json` into `char[] json` so that the bytes are not write protected
|
||||
* Fixed parsing bug when the JSON contains multi-dimensional arrays
|
||||
|
||||
v1.0
|
||||
|
15
CMakeLists.txt
Normal file
15
CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
cmake_minimum_required(VERSION 2.8.4)
|
||||
project(ArduinoJson)
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS -W4)
|
||||
endif()
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonArray.h"
|
||||
#include "JsonHashTable.h"
|
||||
|
||||
JsonArray::JsonArray(char* json, jsmntok_t* tokens)
|
||||
: JsonObjectBase(json, tokens)
|
||||
{
|
||||
if (tokens == 0 || tokens[0].type != JSMN_ARRAY)
|
||||
makeInvalid();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns the token for the value at the specified index
|
||||
*/
|
||||
jsmntok_t* JsonArray::getToken(int index)
|
||||
{
|
||||
// sanity check
|
||||
if (json == 0 || tokens == 0 || index < 0 || index >= tokens[0].size)
|
||||
return 0;
|
||||
|
||||
// skip first token, it's the whole object
|
||||
jsmntok_t* currentToken = tokens + 1;
|
||||
|
||||
// skip all tokens before the specified index
|
||||
for (int i = 0; i < index; i++)
|
||||
{
|
||||
// move forward: current + nested tokens
|
||||
currentToken += 1 + getNestedTokenCount(currentToken);
|
||||
}
|
||||
|
||||
return currentToken;
|
||||
}
|
||||
|
||||
JsonArray JsonArray::getArray(int index)
|
||||
{
|
||||
return JsonArray(json, getToken(index));
|
||||
}
|
||||
|
||||
bool JsonArray::getBool(int index)
|
||||
{
|
||||
return getBoolFromToken(getToken(index));
|
||||
}
|
||||
|
||||
double JsonArray::getDouble(int index)
|
||||
{
|
||||
return getDoubleFromToken(getToken(index));
|
||||
}
|
||||
|
||||
JsonHashTable JsonArray::getHashTable(int index)
|
||||
{
|
||||
return JsonHashTable(json, getToken(index));
|
||||
}
|
||||
|
||||
long JsonArray::getLong(int index)
|
||||
{
|
||||
return getLongFromToken(getToken(index));
|
||||
}
|
||||
|
||||
char* JsonArray::getString(int index)
|
||||
{
|
||||
return getStringFromToken(getToken(index));
|
||||
}
|
42
JsonArray.h
42
JsonArray.h
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#ifndef __JSONARRAY_H
|
||||
#define __JSONARRAY_H
|
||||
|
||||
#include "JsonObjectBase.h"
|
||||
|
||||
class JsonHashTable;
|
||||
|
||||
class JsonArray : public JsonObjectBase
|
||||
{
|
||||
template <int N>
|
||||
friend class JsonParser;
|
||||
|
||||
friend class JsonHashTable;
|
||||
|
||||
public:
|
||||
|
||||
JsonArray() {}
|
||||
|
||||
int getLength()
|
||||
{
|
||||
return tokens != 0 ? tokens[0].size : 0;
|
||||
}
|
||||
|
||||
JsonArray getArray(int index);
|
||||
bool getBool(int index);
|
||||
double getDouble(int index);
|
||||
JsonHashTable getHashTable(int index);
|
||||
long getLong(int index);
|
||||
char* getString(int index);
|
||||
|
||||
private:
|
||||
|
||||
JsonArray(char* json, jsmntok_t* tokens);
|
||||
jsmntok_t* getToken(int index);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonArray.h"
|
||||
#include "JsonHashTable.h"
|
||||
|
||||
#include <string.h> // for strcmp()
|
||||
|
||||
JsonHashTable::JsonHashTable(char* json, jsmntok_t* tokens)
|
||||
: JsonObjectBase(json, tokens)
|
||||
{
|
||||
if (tokens == 0 || tokens[0].type != JSMN_OBJECT)
|
||||
makeInvalid();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the token for the value associated with the specified key
|
||||
*/
|
||||
jsmntok_t* JsonHashTable::getToken(const char* desiredKey)
|
||||
{
|
||||
// sanity check
|
||||
if (json == 0 || tokens == 0 || desiredKey == 0)
|
||||
return 0;
|
||||
|
||||
// skip first token, it's the whole object
|
||||
jsmntok_t* currentToken = tokens + 1;
|
||||
|
||||
// scan each keys
|
||||
for (int i = 0; i < tokens[0].size / 2 ; i++)
|
||||
{
|
||||
// get key token string
|
||||
char* key = getStringFromToken(currentToken);
|
||||
|
||||
// compare with desired name
|
||||
if (strcmp(desiredKey, key) == 0)
|
||||
{
|
||||
// return the value token that follows the key token
|
||||
return currentToken + 1;
|
||||
}
|
||||
|
||||
// move forward: key + value + nested tokens
|
||||
currentToken += 2 + getNestedTokenCount(currentToken + 1);
|
||||
}
|
||||
|
||||
// nothing found, return NULL
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool JsonHashTable::containsKey(const char* key)
|
||||
{
|
||||
return getToken(key) != 0;
|
||||
}
|
||||
|
||||
JsonArray JsonHashTable::getArray(const char* key)
|
||||
{
|
||||
return JsonArray(json, getToken(key));
|
||||
}
|
||||
|
||||
bool JsonHashTable::getBool(const char* key)
|
||||
{
|
||||
return getBoolFromToken(getToken(key));
|
||||
}
|
||||
|
||||
double JsonHashTable::getDouble(const char* key)
|
||||
{
|
||||
return getDoubleFromToken(getToken(key));
|
||||
}
|
||||
|
||||
JsonHashTable JsonHashTable::getHashTable(const char* key)
|
||||
{
|
||||
return JsonHashTable(json, getToken(key));
|
||||
}
|
||||
|
||||
long JsonHashTable::getLong(const char* key)
|
||||
{
|
||||
return getLongFromToken(getToken(key));
|
||||
}
|
||||
|
||||
char* JsonHashTable::getString(const char* key)
|
||||
{
|
||||
return getStringFromToken(getToken(key));
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#ifndef __JSONHASHTABLE_H
|
||||
#define __JSONHASHTABLE_H
|
||||
|
||||
#include "JsonObjectBase.h"
|
||||
|
||||
class JsonArray;
|
||||
|
||||
class JsonHashTable : public JsonObjectBase
|
||||
{
|
||||
template <int N>
|
||||
friend class JsonParser;
|
||||
|
||||
friend class JsonArray;
|
||||
|
||||
public:
|
||||
|
||||
JsonHashTable() {}
|
||||
|
||||
bool containsKey(const char* key);
|
||||
|
||||
JsonArray getArray(const char* key);
|
||||
bool getBool(const char* key);
|
||||
double getDouble(const char* key);
|
||||
JsonHashTable getHashTable(const char* key);
|
||||
long getLong(const char* key);
|
||||
char* getString(const char* key);
|
||||
|
||||
private:
|
||||
|
||||
JsonHashTable(char* json, jsmntok_t* tokens);
|
||||
jsmntok_t* getToken(const char* key);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
#include "JsonObjectBase.h"
|
||||
|
||||
#include <stdlib.h> // for strtol, strtod
|
||||
|
||||
int JsonObjectBase::getNestedTokenCount(jsmntok_t* token)
|
||||
{
|
||||
int end = token->end;
|
||||
int count = 0;
|
||||
|
||||
token++;
|
||||
|
||||
while (token->start < end)
|
||||
{
|
||||
token++;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool JsonObjectBase::getBoolFromToken(jsmntok_t* token)
|
||||
{
|
||||
if (token->type != JSMN_PRIMITIVE) return 0;
|
||||
|
||||
// "true"
|
||||
if (json[token->start] == 't') return true;
|
||||
|
||||
// "false"
|
||||
if (json[token->start] == 'f') return false;
|
||||
|
||||
// "null"
|
||||
if (json[token->start] == 'n') return false;
|
||||
|
||||
// number
|
||||
return strtol(json + token->start, 0, 0) != 0;
|
||||
}
|
||||
|
||||
double JsonObjectBase::getDoubleFromToken(jsmntok_t* token)
|
||||
{
|
||||
if (token == 0 || token->type != JSMN_PRIMITIVE) return 0;
|
||||
|
||||
return strtod(json + token->start, 0);
|
||||
}
|
||||
|
||||
long JsonObjectBase::getLongFromToken(jsmntok_t* token)
|
||||
{
|
||||
if (token == 0 || token->type != JSMN_PRIMITIVE) return 0;
|
||||
|
||||
return strtol(json + token->start, 0, 0);
|
||||
}
|
||||
|
||||
char* JsonObjectBase::getStringFromToken(jsmntok_t* token)
|
||||
{
|
||||
if (token == 0 || token->type != JSMN_PRIMITIVE && token->type != JSMN_STRING)
|
||||
return 0;
|
||||
|
||||
// add null terminator to the string
|
||||
json[token->end] = 0;
|
||||
|
||||
return json + token->start;
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
#ifndef __JSONOBJECTBASE_H
|
||||
#define __JSONOBJECTBASE_H
|
||||
|
||||
#include "utility/jsmn.h"
|
||||
|
||||
class JsonObjectBase
|
||||
{
|
||||
public:
|
||||
|
||||
JsonObjectBase()
|
||||
{
|
||||
makeInvalid();
|
||||
}
|
||||
|
||||
bool success()
|
||||
{
|
||||
return json != 0 && tokens != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
JsonObjectBase(char* json, jsmntok_t* tokens)
|
||||
{
|
||||
this->json = json;
|
||||
this->tokens = tokens;
|
||||
}
|
||||
|
||||
void makeInvalid()
|
||||
{
|
||||
json = 0;
|
||||
tokens = 0;
|
||||
}
|
||||
|
||||
static int getNestedTokenCount(jsmntok_t* token);
|
||||
|
||||
bool getBoolFromToken(jsmntok_t* token);
|
||||
double getDoubleFromToken(jsmntok_t* token);
|
||||
long getLongFromToken(jsmntok_t* token);
|
||||
char* getStringFromToken(jsmntok_t* token);
|
||||
|
||||
char* json;
|
||||
jsmntok_t* tokens;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
69
JsonParser.h
69
JsonParser.h
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#ifndef __JSONPARSER_H
|
||||
#define __JSONPARSER_H
|
||||
|
||||
#include "JsonHashTable.h"
|
||||
#include "JsonArray.h"
|
||||
|
||||
/*
|
||||
* The JSON parser.
|
||||
*
|
||||
* You need to specifiy the number of token to be allocated for that parser.
|
||||
* Values from 16 to 32 are recommended.
|
||||
* The parser size will be MAX_TOKEN*8 bytes.
|
||||
* Don't forget that the memory size of standard Arduino board is only 2KB
|
||||
*
|
||||
* CAUTION: JsonArray and JsonHashTable contain pointers to tokens of the
|
||||
* JsonParser, so they need the JsonParser to be in memory to work.
|
||||
* As a result, you must not create JsonArray and JsonHashTable that have a
|
||||
* longer life that the JsonParser.
|
||||
*/
|
||||
template <int MAX_TOKENS>
|
||||
class JsonParser
|
||||
{
|
||||
public:
|
||||
|
||||
/*
|
||||
* Parse the JSON string and return a array.
|
||||
*
|
||||
* The content of the string may be altered to add '\0' at the
|
||||
* end of string tokens
|
||||
*/
|
||||
JsonArray parseArray(char* json)
|
||||
{
|
||||
return JsonArray(json, parse(json));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the JSON string and return a array.
|
||||
*
|
||||
* The content of the string may be altered to add '\0' at the
|
||||
* end of string tokens
|
||||
*/
|
||||
JsonHashTable parseHashTable(char* json)
|
||||
{
|
||||
return JsonHashTable(json, parse(json));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
jsmntok_t* parse(char* json)
|
||||
{
|
||||
jsmn_parser parser;
|
||||
jsmn_init(&parser);
|
||||
|
||||
if (JSMN_SUCCESS != jsmn_parse(&parser, json, tokens, MAX_TOKENS))
|
||||
return 0;
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
jsmntok_t tokens[MAX_TOKENS];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
10
LICENSE.md
Normal file
10
LICENSE.md
Normal file
@ -0,0 +1,10 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014 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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
426
README.md
426
README.md
@ -1,409 +1,79 @@
|
||||
An efficient JSON parser for Arduino
|
||||
====================================
|
||||
Arduino JSON library
|
||||
====================
|
||||
|
||||
This library is an thin C++ wrapper around the *jsmn* tokenizer: http://zserge.com/jsmn.html
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
|
||||
It's design to be very lightweight, works without any allocation on the heap (no malloc) and supports nested objects.
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library on any other C++ project.
|
||||
It's design to have the most intuitive API, the smallest footprint and works 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.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Based on the well-proven [jsmn](http://zserge.com/jsmn.html) tokenizer
|
||||
* Supports nested objects
|
||||
* Works with fixed memory allocation : no `malloc()`
|
||||
* Low footprint
|
||||
* JSON decoding
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, very easy to use
|
||||
* Fixed memory allocation (no malloc)
|
||||
* Small footprint
|
||||
* MIT License
|
||||
|
||||
Quick start
|
||||
-----------
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
char json[] = "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}";
|
||||
|
||||
JsonParser<32> parser;
|
||||
|
||||
JsonHashTable hashTable = parser.parseHashTable(json);
|
||||
|
||||
if (!hashTable.success())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char* name = hashTable.getString("Name");
|
||||
|
||||
JsonArray skills = hashTable.getArray("Skills");
|
||||
|
||||
int age = hashTable.getLong("Age");
|
||||
|
||||
bool online = hashTable.getBool("Online");
|
||||
|
||||
|
||||
|
||||
How to use ?
|
||||
-------------
|
||||
|
||||
### 1. Install the library
|
||||
|
||||
Download the library and extract it to:
|
||||
|
||||
<your Arduino Sketch folder>/libraries/ArduinoJsonParser
|
||||
|
||||
### 2. Import in your sketch
|
||||
|
||||
Just add the following line on the top of your `.ino` file:
|
||||
|
||||
#include <JsonParser.h>
|
||||
|
||||
### 3. Create a parser
|
||||
|
||||
To extract data from the JSON string, you need to create a `JsonParser`, and specify the number of token you allocate for the parser itself:
|
||||
|
||||
JsonParser<32> parser;
|
||||
|
||||
> #### How to choose the number of tokens ?
|
||||
|
||||
> A token is an element of the JSON object: either a key, a value, an hash-table or an array.
|
||||
> As an example the `char json[]` on the top of this page contains 12 tokens (don't forget to count 1 for the whole object and 1 more for the array itself).
|
||||
|
||||
> The more tokens you allocate, the more complex the JSON can be, but also the more memory is occupied.
|
||||
> Each token takes 8 bytes, so `sizeof(JsonParser<32>)` is 256 bytes which is quite big in an Arduino with only 2KB of RAM.
|
||||
> Don't forget that you also have to store the JSON string in RAM and it's probably big.
|
||||
|
||||
> 32 tokens may seem small, but it's very decent for an 8-bit processor, you wouldn't get better results with other JSON libraries.
|
||||
|
||||
### 4. Extract data
|
||||
|
||||
To use this library, you need to know beforehand what is the type of data contained in the JSON string, which is very likely.
|
||||
|
||||
The root object has to be either a hash-table (like `{"key":"value"}`) or an array (like `[1,2]`).
|
||||
|
||||
The nested objects can be either arrays, booleans, hash-tables, numbers or strings.
|
||||
If you need other type, you can get the string value and parse it yourself.
|
||||
|
||||
#### Hash-table
|
||||
|
||||
Consider we have a `char json[]` containing to the following JSON string:
|
||||
|
||||
{
|
||||
"Name":"Blanchon",
|
||||
"Skills":[
|
||||
"C",
|
||||
"C++",
|
||||
"C#"],
|
||||
"Age":32,
|
||||
"Online":true
|
||||
}
|
||||
|
||||
In this case the root object of the JSON string is a hash-table, so you need to extract a `JsonHashTable`:
|
||||
#### Decoding / Parsing
|
||||
|
||||
JsonHashTable root = parser.parseHashTable(json);
|
||||
|
||||
To check if the parsing was successful, you must check:
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
if (!root.success())
|
||||
{
|
||||
// Parsing fail: could be an invalid JSON, or too many tokens
|
||||
}
|
||||
|
||||
And then extract the member you need:
|
||||
|
||||
char* name = hashTable.getString("Name");
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonArray skills = hashTable.getArray("Skills");
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
int age = hashTable.getLong("Age");
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
bool online = hashTable.getBool("Online");
|
||||
|
||||
#### Array
|
||||
[See complete guide](/doc/Decoding JSON.md)
|
||||
|
||||
Consider we have a `char json[]` containing to the following JSON string:
|
||||
|
||||
[
|
||||
[ 1.2, 3.4 ],
|
||||
[ 5.6, 7.8 ]
|
||||
]
|
||||
|
||||
In this case the root object of the JSON string is an array, so you need to extract a `JsonArray`:
|
||||
#### Encoding / Generating
|
||||
|
||||
JsonArray root = parser.parseArray(json);
|
||||
|
||||
To check if the parsing was successful, you must check:
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
if (!root.success())
|
||||
{
|
||||
// Parsing fail: could be an invalid JSON, or too many tokens
|
||||
}
|
||||
|
||||
And then extract the content by its index in the array:
|
||||
|
||||
JsonArray row0 = root.getArray(0);
|
||||
double a = row0.getDouble(0);
|
||||
|
||||
or simply:
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
double a = root.getArray(0).getDouble(0);
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
Common pitfalls
|
||||
---------------
|
||||
[See complete guide](/doc/Encoding JSON.md)
|
||||
|
||||
### 1. Not enough tokens
|
||||
|
||||
By design, the library has no way to tell you why `JsonParser::parseArray()` or `JsonParser::parseHashTable()` failed.
|
||||
|
||||
There are basically two reasons why they may fail:
|
||||
|
||||
1. the JSON string is invalid
|
||||
2. the JSON string contains more tokens that the parser can store
|
||||
|
||||
So, if you are sure the JSON string is correct and you still can't parse it, you should slightly increase the number of token of the parser.
|
||||
|
||||
### 2. Not enough memory
|
||||
|
||||
You may go into unpredictable trouble if you allocate more memory than your processor really has.
|
||||
It's a very common issue in embedded development.
|
||||
|
||||
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
|
||||
|
||||
For example, don't do this:
|
||||
|
||||
char json[1024]; // 1 KB
|
||||
JsonParser<64> parser; // 512 B
|
||||
|
||||
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
|
||||
|
||||
That is why an 8-bit processor is not able to parse long and complex JSON strings.
|
||||
|
||||
### 3. JsonParser not in memory
|
||||
|
||||
To reduce the memory consumption, `JsonArray` and `JsonHashTable` contains pointer to the token that are inside the `JsonParser`. This can only work if the `JsonParser` is still in memory.
|
||||
|
||||
For example, don't do this:
|
||||
|
||||
JsonArray getArray(char* json)
|
||||
{
|
||||
JsonParser<16> parser;
|
||||
return parser.parseArray(parser);
|
||||
}
|
||||
|
||||
because the local variable `parser` will be *removed* from memory when the function `getArray()` returns, and the pointer inside `JsonArray` will point to an invalid location.
|
||||
|
||||
### 4. JSON string is altered
|
||||
|
||||
This will probably never be an issue, but you need to be aware of this feature.
|
||||
|
||||
When you pass a `char[]` to `JsonParser::parseArray()` or `JsonParser::parseHashTable()`, the content of the string will be altered to add `\0` at the end of the tokens.
|
||||
|
||||
This is because we want functions like `JsonArray::getString()` to return a null-terminating string without any memory allocation.
|
||||
|
||||
|
||||
Memory usage
|
||||
Testimonials
|
||||
------------
|
||||
|
||||
Here are the size of the main classes of the library.
|
||||
From Arduino's Forum user `jflaplante`:
|
||||
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
|
||||
> I have no such problem so far with your library. It is working perfectly with my web services.
|
||||
|
||||
This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor.
|
||||
From Arduino's Forum user `gbathree`:
|
||||
> Thanks so much - this is an awesome library! If you want to see what we're doing with it - the project is located at www.photosynq.org.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Size in bytes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Parser<N></td>
|
||||
<td>8 x N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray</td>
|
||||
<td>4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable</td>
|
||||
<td>4</td>
|
||||
</tr>
|
||||
</table>
|
||||
From StackOverflow user `thegreendroid`:
|
||||
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
|
||||
|
||||
From GitHub user `zacsketches`:
|
||||
|
||||
Code size
|
||||
---------
|
||||
> Thanks for a great library!!!
|
||||
> I've been watching you consistently develop this library over the past six months, and I used it today for a publish and subscribe architecture designed to help hobbyists move into more advanced robotics. Your library allowed me to implement remote subscription in order to facilitate multi-processor robots.
|
||||
> ArduinoJson saved me a week's worth of time!!
|
||||
|
||||
Theses tables has been created by analyzing the map file generated by AVR-GCC after adding `-Wl,-Map,foo.map` to the command line.
|
||||
---
|
||||
|
||||
As you'll see the code size if between 1680 and 3528 bytes, depending on the features you use.
|
||||
|
||||
### Minimum setup
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Size in bytes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>strcmp(char*,char*)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>jsmn_init(jsmn_parser*)</td>
|
||||
<td>20</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>jsmn_parse(jsmn_parser*, char const*, jsmntok_t*, unsigned int)</td>
|
||||
<td>960</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonParser::parse(char*)</td>
|
||||
<td>106</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonObjectBase::getNestedTokenCount(jsmntok_t*)</td>
|
||||
<td>84</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonObjectBase::getStringFromToken(jsmntok_t*)</td>
|
||||
<td>68</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::JsonArray(char*, jsmntok_t*)</td>
|
||||
<td>42</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::getToken(int)</td>
|
||||
<td>112</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::getString(int)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::JsonHashTable(char*, jsmntok_t*)</td>
|
||||
<td>42</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::getToken(char*)</td>
|
||||
<td>180</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::getString(char*)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TOTAL</td>
|
||||
<td>1680</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Additional space to parse nested objects
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Size in bytes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::getArray(int)</td>
|
||||
<td>42</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::getHashTable(int)</td>
|
||||
<td>64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::getArray(char*)</td>
|
||||
<td>64</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::getHashTable(char*)</td>
|
||||
<td>42</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TOTAL</td>
|
||||
<td>212</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Additional space to parse `bool` values
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Size in bytes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonObjectBase::getBoolFromToken(jsmntok_t*)</td>
|
||||
<td>82</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::getBool(int)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::getBool(char*)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TOTAL</td>
|
||||
<td>130</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Additional space to parse `double` values
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Size in bytes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>strtod(char*,int)</td>
|
||||
<td>704</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonObjectBase::getDoubleFromToken(jsmntok_t*)</td>
|
||||
<td>44</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::getDouble(int)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::getDouble(char*)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TOTAL</td>
|
||||
<td>796</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Additional space to parse `long` values
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Function</th>
|
||||
<th>Size in bytes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>strtol(char*,char**,int)</td>
|
||||
<td>606</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonObjectBase::getLongFromToken(jsmntok_t*)</td>
|
||||
<td>56</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonArray::getLong(int)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>JsonHashTable::getLong(char*)</td>
|
||||
<td>18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TOTAL</td>
|
||||
<td>710</td>
|
||||
</tr>
|
||||
</table>
|
||||
Found this library useful? [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:
|
102
doc/Avoiding pitfalls.md
Normal file
102
doc/Avoiding pitfalls.md
Normal file
@ -0,0 +1,102 @@
|
||||
Avoiding common pitfalls in Arduino JSON
|
||||
========================================
|
||||
|
||||
As `StaticJsonBuffer` is the corner stone of this library, you'll see that every pitfall listed here are related to a wrong understanding of the memory model.
|
||||
|
||||
Make sure you read [Arduino JSON memory model](Memory model.md) before going further.
|
||||
|
||||
## 1. Make `StaticJsonBuffer` big enough
|
||||
|
||||
By design, the library has no way to tell you why `parseArray()` or `parseObject()` failed.
|
||||
|
||||
There are basically two reasons why they may fail:
|
||||
|
||||
1. the JSON string is invalid,
|
||||
2. the JSON string contains more values that the buffer can store.
|
||||
|
||||
So, if you are sure the JSON string is correct and you still can't parse it, you should try to increase the size of the `StaticJsonBuffer`.
|
||||
|
||||
## 2. Make sure everything fits in memory
|
||||
|
||||
You may go into unpredictable trouble if you allocate more memory than your processor really has.
|
||||
It's a very common issue in embedded development.
|
||||
|
||||
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
|
||||
|
||||
For example, don't do this:
|
||||
|
||||
char json[1024]; // 1 KB
|
||||
StaticJsonBuffer<512> buffer; // 514 B
|
||||
|
||||
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
|
||||
|
||||
That is why an 8-bit processor is not able to parse long and complex JSON strings.
|
||||
|
||||
## 3. Keep the `StaticJsonBuffer` in memory long enough
|
||||
|
||||
Remember that `StaticJsonBuffer`'s function return references.
|
||||
References don't contain data, they are just pointer to the actual.
|
||||
So they can only work if the actual data is in memory.
|
||||
|
||||
For example, don't do this:
|
||||
|
||||
JsonArray& getArray(char* json)
|
||||
{
|
||||
StaticJsonBuffer<200> buffer;
|
||||
return buffer.parseArray(json);
|
||||
}
|
||||
|
||||
because the local variable `buffer` will be *removed* from memory when the function `parseArray()` returns, and the `JsonArray&` will point to an invalid location.
|
||||
|
||||
## 4. Don't reuse the same `StaticJsonBuffer`
|
||||
|
||||
During is lifetime a `StaticJsonBuffer` growth until it's discarded. If you try to reuse the same instance several time, it will rapidly get full.
|
||||
|
||||
For this reason, you should not use a global variable for your `StaticJsonBuffer`. I don't think there is any scenario in which a global `StaticJsonBuffer` would be a valid option.
|
||||
|
||||
The best practice is to declare it in a local scope, so that it's discarded as soon as possible. My advice it to declare it in a function which unique role is to handle the JSON serialization.
|
||||
|
||||
## 5. Keep the JSON string in memory long enough
|
||||
|
||||
The library never make memory duplication.
|
||||
This has an important implication on string values, it means that the library will return pointer to chunks of the string.
|
||||
|
||||
For instance, let's imagine that you parse `["hello","world"]`, like this:
|
||||
|
||||
char[] json = "[\"hello\",\"world\"]";
|
||||
StaticJsonBuffer<32> buffer;
|
||||
JsonArray& array = buffer.parseArray(json);
|
||||
|
||||
const char* first = array[0];
|
||||
const char* second = array[1];
|
||||
|
||||
In that case, both `first` and `second` are pointers to the content of the original string `json`.
|
||||
So this will only work if `json` is still in memory.
|
||||
|
||||
## 6. JSON string is altered
|
||||
|
||||
If you read carefully the previous section, you may have come to the conclusion that the JSON parser modifies the JSON string.
|
||||
|
||||
Indeed, the parser modifies the string for two reasons:
|
||||
|
||||
1. it inserts `\0` to terminate substrings,
|
||||
2. it translate escaped characters like `\n` or `\t`.
|
||||
|
||||
Most of the time this wont be an issue, but there are some corner cases that can be problematic.
|
||||
|
||||
Let take the example bellow:
|
||||
|
||||
char[] json = "[\"hello\",\"world\"]";
|
||||
StaticJsonBuffer<32> buffer;
|
||||
JsonArray& array = buffer.parseArray(json);
|
||||
|
||||
If you replace it by:
|
||||
|
||||
char* json = "[\"hello\",\"world\"]";
|
||||
StaticJsonBuffer<32> buffer;
|
||||
JsonArray& array = buffer.parseArray(json);
|
||||
|
||||
Depending on your platform, you may have an exception because the parser tries to write at a location that is read-only.
|
||||
In the first case `char json[]` declares an array of `char` initialized to the specified string.
|
||||
In the second case `char* json` declares a pointer to a read-only string, in fact it should be a `const char*` instead of a `char*`.
|
||||
|
15
doc/Contributing.md
Normal file
15
doc/Contributing.md
Normal file
@ -0,0 +1,15 @@
|
||||
Contributing to Arduino JSON
|
||||
============================
|
||||
|
||||
If you want to contribute to the project, please:
|
||||
|
||||
1. Use GitHub pull request feature
|
||||
2. Follow the coding conventions
|
||||
3. Write tests
|
||||
|
||||
About the coding conventions: I try to follow the [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html) with few variations to match the Arduino conventions.
|
||||
|
||||
I use [ClangFormat](http://clang.llvm.org/docs/ClangFormat.html) to format the code for me.
|
||||
I use [CppLint](http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py) to detect non-compliant stuff.
|
||||
|
||||
You should have a look at the `scripts/` folder as it contains a few helpers scripts.
|
148
doc/Decoding JSON.md
Normal file
148
doc/Decoding JSON.md
Normal file
@ -0,0 +1,148 @@
|
||||
Decoding JSON with Arduino JSON
|
||||
===============================
|
||||
|
||||
Before writing any code, don't forget to include the header:
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
For instructions on how to install the library, please read [Using the library with Arduino](Using the library with Arduino.md) or [Using the library without Arduino](Using the library without Arduino.md).
|
||||
|
||||
## Example
|
||||
|
||||
Here an example that parse the string `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`:
|
||||
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
//
|
||||
// Step 1: Reserve memory space
|
||||
//
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
//
|
||||
// Step 2: Deserialize the JSON string
|
||||
//
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
if (!root.success())
|
||||
{
|
||||
Serial.println("parseObject() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Step 3: Retrieve the values
|
||||
//
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
## Step 1: Reserve memory space
|
||||
|
||||
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer`.
|
||||
|
||||
Before continuing please read the page [Arduino JSON memory model](Memory model.md) that explains everything you need to know about `StaticJsonBuffer`.
|
||||
|
||||
## Step 2: Parse the JSON string
|
||||
|
||||
You invoke the JSON parser through the instance of `StaticJsonBuffer`.
|
||||
It exposes two functions for parsing JSON:
|
||||
|
||||
1. `parseArray()` that returns a reference to a `JsonArray`
|
||||
2. `parseObject()` that returns a reference to a `JsonObject`
|
||||
|
||||
Let's see an example.
|
||||
Say we want to parse `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`, it's an object so we call `parseObject()` as follows:
|
||||
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
As you can see `parseObject()` takes a `char*` as a parameter.
|
||||
Be careful, it's not a `const char*`, the memory must be writable.
|
||||
Indeed, the parser will modify the string in two cases:
|
||||
|
||||
1. to insert string endings (character `\0`),
|
||||
2. to translate escaped characters (like `\n` or `\t`).
|
||||
|
||||
Another thing that you must keep in mind is that the string (`char json[]` in the example above) must stay in memory during the whole parsing process.
|
||||
That is because the in memory object tree will store pointer to chunks of the string, so as to avoid any memory duplication.
|
||||
|
||||
Now, to check if the parsing was successful, you can call `JsonObject::success()`:
|
||||
|
||||
if (!root.success())
|
||||
{
|
||||
// Parsing fail
|
||||
}
|
||||
|
||||
The result can be `false` for tree reasons:
|
||||
|
||||
1. the JSON string is invalid,
|
||||
2. the JSON string doesn't represent an object,
|
||||
3. the `StaticJsonBuffer` is too small.
|
||||
|
||||
We just saw how to parse an object, there is nothing more to say for arrays, the procedure is exactly the same.
|
||||
|
||||
## Step 3: Retrieve the values
|
||||
|
||||
Now that the object or array is in memory, you can extract the data very easily.
|
||||
|
||||
In this section, we'll see how to do it with a `JsonObject`.
|
||||
Once again, there is nothing more to say about arrays, `JsonArray` works exactly the same as `JsonObject`.
|
||||
|
||||
#### Subscript operator
|
||||
|
||||
The simplest way is to use the subscript operator of `JsonObject`:
|
||||
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
|
||||
You can chain the subscript operator if you have nested arrays or objects:
|
||||
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
But alternatively, you can get a reference to the nested array:
|
||||
|
||||
JsonArray& nestedArray = root["data"];
|
||||
|
||||
#### Casting values
|
||||
|
||||
In the previous examples, the values were implicitly casted to the target type.
|
||||
You can also do this explicitly
|
||||
|
||||
const char* sensor = root["sensor"].asString();
|
||||
long time = root["time"].as<long>();
|
||||
JsonArray& nestedArray = root["data"].asArray();
|
||||
|
||||
If the actual value doesn't match the target type, a default value will be return:
|
||||
|
||||
1. `false` for boolean values
|
||||
2. `0` for integer values
|
||||
3. `NULL` for string values
|
||||
4. `JsonArray::invalid()` for nested arrays
|
||||
5. `JsonObject::invalid()` for nested object
|
||||
|
||||
#### Check values
|
||||
|
||||
If you want to know if some value is present, call `containsKey()`:
|
||||
|
||||
if (root.contains("extra"))
|
||||
{
|
||||
// root["extra"] is valid
|
||||
}
|
||||
|
||||
If you want to check the type value has a certain type, call `is<T>()`:
|
||||
|
||||
if (root["extra"].is<JsonArray&>())
|
||||
{
|
||||
// root["extra"] is an array
|
||||
}
|
||||
|
||||
You can also iterate through the key-value pairs of the object:
|
||||
|
||||
for (JsonObject::itertor it=root.begin(); it!=root.end(); ++it)
|
||||
{
|
||||
Serial.println(it->key);
|
||||
Serial.println(i->value.asString());
|
||||
}
|
140
doc/Encoding JSON.md
Normal file
140
doc/Encoding JSON.md
Normal file
@ -0,0 +1,140 @@
|
||||
Encoding JSON with Arduino JSON
|
||||
===============================
|
||||
|
||||
Before writing any code, don't forget to include the header:
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
For instructions on how to install the library, please read [Using the library with Arduino](Using the library with Arduino.md) or [Using the library without Arduino](Using the library without Arduino.md).
|
||||
|
||||
## Example
|
||||
|
||||
Here is an example to generate `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`
|
||||
|
||||
//
|
||||
// Step 1: Reserve memory space
|
||||
//
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
//
|
||||
// Step 2: Build object tree in memory
|
||||
//
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||
|
||||
//
|
||||
// Step 3: Generate the JSON string
|
||||
//
|
||||
root.printTo(Serial);
|
||||
|
||||
## Step 1: Reserve memory space
|
||||
|
||||
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer`.
|
||||
|
||||
Before continuing please read the page [Arduino JSON memory model](Memory model.md) that explains everything you need to know about `StaticJsonBuffer`.
|
||||
|
||||
## Step 2: Build object tree in memory
|
||||
|
||||
Now that you have enough memory hold by the `StaticJsonBuffer`, you can use it to build your in-memory representation of the JSON string.
|
||||
|
||||
#### Arrays
|
||||
|
||||
You create an array like this:
|
||||
|
||||
JsonArray& array = jsonBuffer.createArray();
|
||||
|
||||
Don't forget the `&` after `JsonArray`, it needs to be a reference to the array.
|
||||
|
||||
Then you can add strings, integer, booleans, etc:
|
||||
|
||||
array.add("bazinga!");
|
||||
array.add(42);
|
||||
array.add(true);
|
||||
|
||||
There are two syntaxes for floating point values:
|
||||
|
||||
array.add(3.1415, 4); // 4 digits: "3.1415"
|
||||
array.add(3.1415); // 2 digits: "3.14"
|
||||
|
||||
> ##### About floating point precision
|
||||
> The overload of `add()` with 2 parameters allows you to specify the number of decimals to save in the JSON string.
|
||||
> When you use the overload with one parameter, you use the default number of decimals which is 2.
|
||||
> Note that this behavior is the exact same as Arduino's `Print::print(double,int);` which is implemented by `Serial`, so you may already be familiar with this behavior.
|
||||
|
||||
You can add a nested array or object if you have a reference to it.
|
||||
Or simpler, you can create nested array or nested objects from the array:
|
||||
|
||||
JsonArray& nestedArray = array.createNestedArray();
|
||||
JsonObject& nestedObject = array.createNestedObject();
|
||||
|
||||
#### Objects
|
||||
|
||||
You create an object like this:
|
||||
|
||||
JsonObject& object = jsonBuffer.createObject();
|
||||
|
||||
Again, don't forget the `&` after `JsonObject`, it needs to be a reference to the object.
|
||||
|
||||
Then you can add strings, integer, booleans, etc:
|
||||
|
||||
object["key1"] = "bazinga!";
|
||||
object["key2"] = 42;
|
||||
object["key3"] = true;
|
||||
|
||||
As for the arrays, there are two syntaxes for the floating point values:
|
||||
|
||||
object["key4"].set(3.1415, 4); // 4 digits "3.1415"
|
||||
object["key5"] = 3.1415; // default: 2 digits "3.14"
|
||||
|
||||
You can add a nested array or object if you have a reference to it.
|
||||
Or simpler, you can create nested array or nested objects from the object:
|
||||
|
||||
JsonArray& nestedArray = object.createNestedArray("key6");
|
||||
JsonObject& nestedObject = object.createNestedObject("key7");
|
||||
|
||||
> ##### Other JsonObject functions
|
||||
> * `object.add(key, value)` is a synonym for `object[key] = value`
|
||||
> * `object.containsKey(key)` returns `true` is the `key` is present in `object`
|
||||
> * `object.remove(key)` removes the `value` associated with `key`
|
||||
|
||||
## Step 3: Generate the JSON string
|
||||
|
||||
There are two ways tho get the resulting JSON string.
|
||||
|
||||
Depending on your project, you may need to dump the string in a classic `char[]` or send it to a `Print` implementation like `Serial` or `EthernetClient `.
|
||||
|
||||
Both ways are the easy way :-)
|
||||
|
||||
#### Use a classic `char[]`
|
||||
|
||||
Whether you have a `JsonArray&` or a `JsonObject&`, simply call `printTo()` with the destination buffer, like so:
|
||||
|
||||
char buffer[256];
|
||||
array.printTo(buffer, sizeof(buffer));
|
||||
|
||||
> ##### Want an indented output?
|
||||
> By default the generated JSON is as small as possible. It contains no extra space, nor line break.
|
||||
> But if you want an indented, more readable output, you can.
|
||||
> Simply call `prettyPrintTo` instead of `printTo()`:
|
||||
>
|
||||
> array.prettyPrintTo(buffer, sizeof(buffer));
|
||||
|
||||
#### Send to a `Print` implementation
|
||||
|
||||
It's very likely that the generated JSON will end up in a stream like `Serial` or `EthernetClient `, so you can save some time and memory by doing this:
|
||||
|
||||
array.printTo(Serial);
|
||||
|
||||
And, of course if you need an indented JSON string:
|
||||
|
||||
array.prettyPrintTo(Serial);
|
||||
|
||||
> ##### About the Print interface
|
||||
> The library is designed to send the JSON string to an implementation of the `Print` interface that is part of Arduino.
|
||||
> In the example above we used `Serial`, but they are many other implementations that would work as well, including: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`, `Wire`...
|
||||
> When you use this library out of the Arduino environment, it will use it's own implementation of `Print` and everything will be the same.
|
58
doc/Memory model.md
Normal file
58
doc/Memory model.md
Normal file
@ -0,0 +1,58 @@
|
||||
Arduino JSON memory model
|
||||
=========================
|
||||
|
||||
## Fixed memory allocation
|
||||
|
||||
### Introducing `StaticJsonBuffer`
|
||||
|
||||
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer` class.
|
||||
|
||||
Before using any function of the library you need to create a `StaticJsonBuffer`. Then you can use this instance to create arrays and objects, or parse a JSON string.
|
||||
|
||||
`StaticJsonBuffer` has a template parameter that determines its capacity. For example, the following line create a `StaticJsonBuffer` with a capacity of 200 bytes:
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
The bigger the buffer is, the more complex the object tree can be, but also the more memory you need.
|
||||
|
||||
### How to determine the buffer size?
|
||||
|
||||
So the big question you should have in mind right now is *How can I determine the size?*.
|
||||
|
||||
There are basically two approaches here:
|
||||
|
||||
1. either you can predict the content of the object tree,
|
||||
2. or, you know how much memory is available.
|
||||
|
||||
In the first case, you know some constraints on the object tree. For instance, let's say that your know in advance (and by that I mean "at compilation time") that you want to generate an object with 3 values, one of them being an array with 2 values, like the following:
|
||||
|
||||
{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
To determine the memory usage of this object tree, you use the two macros `JSON_ARRAY_SIZE(n)` and `JSON_OBJECT_SIZE(n)`, both take the number of elements as an argument.
|
||||
For the example above, it would be:
|
||||
|
||||
const int BUFFER_SIZE = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2);
|
||||
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
|
||||
|
||||
In the second case, let's say you dynamically generate a JSON object tree of a random complexity so you can't put a limit based on that. But on the other hand, you don't want your program to crash because the object tree doesn't fit in memory.
|
||||
The solution here is to determine how much memory is available, or in other words how much memory you can afford for the JSON object tree.
|
||||
|
||||
### Why choosing fixed allocation?
|
||||
|
||||
This fixed allocation approach may seem a bit strange, especially if your a desktop application developer used to dynamic allocation, but it make a lot of sense in an embedded context:
|
||||
|
||||
1. the code is smaller
|
||||
2. it uses less memory
|
||||
3. it doesn't create memory fragmentation
|
||||
4. it predictable
|
||||
|
||||
Don't forget that the memory is "freed" as soon as the `StaticJsonBuffer` is out of scope, like any other variable. It only hold the memory for a short amount of time.
|
||||
|
||||
## Memory usage
|
||||
|
||||
#### Object size for 8-bit AVR
|
||||
|
||||
| Type | Size |
|
||||
|-------------------------|------------|
|
||||
| JsonArray of N element | 4 + 8 * N |
|
||||
| JsonObject of N element | 4 + 10 * N |
|
80
doc/Migrating code to new API.md
Normal file
80
doc/Migrating code to new API.md
Normal file
@ -0,0 +1,80 @@
|
||||
Migrating code written for Arduino JSON v3 to v4
|
||||
================================================
|
||||
|
||||
Arduino JSON v4 was a major rewrite of the library, and the API changed significantly.
|
||||
|
||||
## Includes
|
||||
|
||||
Arduino JSON v3 had two include files:
|
||||
|
||||
#include <JsonParser.h>
|
||||
#include <JsonGenerator.h>
|
||||
|
||||
Arduino JSON v4 only has one:
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
## Namespaces
|
||||
|
||||
Arduino JSON v3 had two namespaces:
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
using namespace ArduinoJson::Generator;
|
||||
|
||||
Arduino JSON v4 doesn't require the `using namespace` statement.
|
||||
It has a namespace but the `using namespace` is done in the header file.
|
||||
|
||||
## StaticJsonBuffer
|
||||
|
||||
Arduino JSON v3 had different memory allocation models for the parser:
|
||||
|
||||
JsonParser<16> parser; // 16 being the capacity in "tokens"
|
||||
|
||||
and for the generator:
|
||||
|
||||
JsonArray<4> array; // 4 being the number of element
|
||||
JsonObject<4> object;
|
||||
|
||||
Arduino JSON v4 only has one memory allocation model:
|
||||
|
||||
StaticJsonBuffer<128> buffer; // 128 being the capacity in bytes
|
||||
|
||||
## Return values for the parser
|
||||
|
||||
Arduino JSON v3 returned value types:
|
||||
|
||||
JsonArray array = parser.parseArray(json);
|
||||
JsonObject object = parser.parseObject(json);
|
||||
|
||||
Arduino JSON v4 returns references types:
|
||||
|
||||
JsonArray& array = buffer.parseArray(json);
|
||||
JsonObject& object = buffer.parseObject(json);
|
||||
|
||||
Everything else is compatible
|
||||
|
||||
## Creating arrays and objects
|
||||
|
||||
Arduino JSON v3 allowed to create `JsonArray` and `JsonObject` directly:
|
||||
|
||||
JsonArray<4> array;
|
||||
JsonObject<4> object;
|
||||
|
||||
Arduino JSON v4 requires that you use a `StaticJsonBuffer` for that:
|
||||
|
||||
JsonArray& array = buffer.createArray();
|
||||
JsonObject& object = buffer.createObject();
|
||||
|
||||
Note: you don't have to specify the capacity anymore.
|
||||
|
||||
## Printable interface
|
||||
|
||||
Arduino JSON v3 used to implement the Printable interface, which allowed statements like:
|
||||
|
||||
Serial.print(array);
|
||||
|
||||
But Arduino JSON v4 doesn't, instead you need to write this:
|
||||
|
||||
array.printTo(Serial);
|
||||
|
||||
Note: there was a good reason for removing that feature, and it's reducing the size of `JsonArray` and `JsonObject`.
|
30
doc/Using the library with Arduino.md
Normal file
30
doc/Using the library with Arduino.md
Normal file
@ -0,0 +1,30 @@
|
||||
Using the library with Arduino
|
||||
==============================
|
||||
|
||||
This library is primarily design to be used with the Arduino IDE and therefore has a simplified setup procedure for that environment.
|
||||
If you don't use the Arduino IDE, please read [Using the library without Arduino](Using the library without Arduino.md).
|
||||
|
||||
## Install the library
|
||||
|
||||
[Download the zip package](https://github.com/bblanchon/ArduinoJson/releases) and extract it to:
|
||||
|
||||
<your Arduino Sketch folder>/libraries/ArduinoJson
|
||||
|
||||
Then restart the Arduino IDE.
|
||||
|
||||
## Run the examples sketches
|
||||
|
||||
Click `File` / `Example` / `ArduinoJson`.
|
||||
|
||||

|
||||
|
||||
## Use the library in your sketches
|
||||
|
||||
Just add the following line at the top of your program:
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
Then follow the instructions:
|
||||
|
||||
1. [Parsing JSON](Parsin JSON.md)
|
||||
2. [Generating JSON](Generating JSON.md)
|
37
doc/Using the library without Arduino.md
Normal file
37
doc/Using the library without Arduino.md
Normal file
@ -0,0 +1,37 @@
|
||||
Using the library without Arduino
|
||||
=================================
|
||||
|
||||
This library is primarily design to be used with the Arduino IDE and therefore has a simplified setup procedure for that environment.
|
||||
If you use the Arduino IDE, please read [Using the library with Arduino](Using the library with Arduino.md).
|
||||
|
||||
However, it can be used without Arduino IDE with very little effort.
|
||||
|
||||
## Compiling the library
|
||||
|
||||
Step 1: Download source code:
|
||||
|
||||
git clone https://github.com/bblanchon/ArduinoJson.git
|
||||
|
||||
Step 2: Generate the `Makefile` for your environment
|
||||
|
||||
cd ArduinoJson
|
||||
cmake .
|
||||
|
||||
Step 3: Build
|
||||
|
||||
make
|
||||
|
||||
## File paths
|
||||
|
||||
Assuming you installed the library into `<arduino-json>`, you need to add:
|
||||
|
||||
1. `<arduino-json>/include` to your include path
|
||||
2. `<arduino-json>/lib` to your library path
|
||||
|
||||
|
||||
----------
|
||||
|
||||
You are now ready to follow the instructions:
|
||||
|
||||
1. [Parsing JSON](Parsin JSON.md)
|
||||
2. [Generating JSON](Generating JSON.md)
|
30
examples/IndentedPrintExample/IndentedPrintExample.ino
Normal file
30
examples/IndentedPrintExample/IndentedPrintExample.ino
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Arduino JSON library - IndentedPrint example
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
IndentedPrint serial(Serial);
|
||||
serial.setTabSize(4);
|
||||
|
||||
serial.println("This is at indentation 0");
|
||||
serial.indent();
|
||||
serial.println("This is at indentation 1");
|
||||
serial.println("This is also at indentation 1");
|
||||
serial.indent();
|
||||
serial.println("This is at indentation 2");
|
||||
|
||||
serial.unindent();
|
||||
serial.unindent();
|
||||
serial.println("This is back at indentation 0");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
42
examples/JsonGeneratorExample/JsonGeneratorExample.ino
Normal file
42
examples/JsonGeneratorExample/JsonGeneratorExample.ino
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080, 6); // 6 is the number of decimals to print
|
||||
data.add(2.302038, 6); // if not specified, 2 digits are printed
|
||||
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
Serial.println();
|
||||
|
||||
root.prettyPrintTo(Serial);
|
||||
// This prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
// "time": 1351824120,
|
||||
// "data": [
|
||||
// 48.756080,
|
||||
// 2.302038
|
||||
// ]
|
||||
// }
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
@ -1,94 +1,37 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include <JsonParser.h>
|
||||
|
||||
void ParseAnObject()
|
||||
{
|
||||
char[] json = "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}";
|
||||
|
||||
JsonParser<32> parser;
|
||||
|
||||
Serial.print("Parse ");
|
||||
Serial.println(json);
|
||||
|
||||
JsonHashTable hashTable = parser.parseHashTable(json);
|
||||
|
||||
if (!hashTable.success())
|
||||
{
|
||||
Serial.println("JsonParser.parseHashTable() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
char* name = hashTable.getString("Name");
|
||||
Serial.print("name=");
|
||||
Serial.println(name);
|
||||
|
||||
JsonArray skills = hashTable.getArray("Skills");
|
||||
Serial.println("skills:");
|
||||
for (int i = 0; i < skills.getLength(); i++)
|
||||
{
|
||||
char* value = skills.getString(i);
|
||||
Serial.print(i);
|
||||
Serial.print(" ");
|
||||
Serial.println(value);
|
||||
}
|
||||
|
||||
int age = hashTable.getLong("Age");
|
||||
Serial.print("age=");
|
||||
Serial.println(age);
|
||||
|
||||
bool online = hashTable.getBool("Online");
|
||||
Serial.print("online=");
|
||||
Serial.println(online);
|
||||
}
|
||||
|
||||
void ParseAnArray()
|
||||
{
|
||||
char[] json = "[[1.2,3.4],[5.6,7.8]]";
|
||||
|
||||
JsonParser<32> parser;
|
||||
|
||||
Serial.print("Parse ");
|
||||
Serial.println(json);
|
||||
|
||||
JsonArray array = parser.parseArray(json);
|
||||
|
||||
if (!array.success())
|
||||
{
|
||||
Serial.println("JsonParser.parseArray() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < array.getLength(); i++)
|
||||
{
|
||||
Serial.println(i);
|
||||
|
||||
JsonArray innerArray = array.getArray(i);
|
||||
|
||||
for (int j = 0; j < innerArray.getLength(); j++)
|
||||
{
|
||||
double value = innerArray.getDouble(j);
|
||||
|
||||
Serial.print(" ");
|
||||
Serial.print(j);
|
||||
Serial.print("=");
|
||||
Serial.println(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
ParseAnObject();
|
||||
ParseAnArray();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
}
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
if (!root.success()) {
|
||||
Serial.println("parseObject() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
Serial.println(sensor);
|
||||
Serial.println(time);
|
||||
Serial.println(latitude, 6);
|
||||
Serial.println(longitude, 6);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
11
include/ArduinoJson.h
Normal file
11
include/ArduinoJson.h
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
||||
#include "../include/ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
31
include/ArduinoJson/Arduino/Print.hpp
Normal file
31
include/ArduinoJson/Arduino/Print.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// This class reproduces Arduino's Print
|
||||
class Print {
|
||||
public:
|
||||
virtual ~Print() {}
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
|
||||
size_t print(const char[]);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(long);
|
||||
size_t println();
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <Print.h>
|
||||
|
||||
#endif
|
54
include/ArduinoJson/Internals/IndentedPrint.hpp
Normal file
54
include/ArduinoJson/Internals/IndentedPrint.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
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
|
||||
// for your own purpose, like logging.
|
||||
class IndentedPrint : public Print {
|
||||
public:
|
||||
explicit IndentedPrint(Print &p) : sink(&p) {
|
||||
level = 0;
|
||||
tabSize = 2;
|
||||
isNewLine = true;
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
|
||||
// Adds one level of indentation
|
||||
void indent() {
|
||||
if (level < MAX_LEVEL) level++;
|
||||
}
|
||||
|
||||
// Removes one level of indentation
|
||||
void unindent() {
|
||||
if (level > 0) level--;
|
||||
}
|
||||
|
||||
// Set the number of space printed for each level of indentation
|
||||
void setTabSize(uint8_t n) {
|
||||
if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE;
|
||||
}
|
||||
|
||||
private:
|
||||
Print *sink;
|
||||
uint8_t level : 4;
|
||||
uint8_t tabSize : 3;
|
||||
bool isNewLine : 1;
|
||||
|
||||
size_t writeTabs();
|
||||
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
42
include/ArduinoJson/Internals/JsonParser.hpp
Normal file
42
include/ArduinoJson/Internals/JsonParser.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.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()
|
||||
class JsonParser {
|
||||
public:
|
||||
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
|
||||
: _buffer(buffer), _ptr(json), _nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
private:
|
||||
bool skip(char charToSkip);
|
||||
bool skip(const char *wordToSkip);
|
||||
void skipSpaces();
|
||||
|
||||
void parseAnythingTo(JsonVariant &destination);
|
||||
inline void parseBooleanTo(JsonVariant &destination);
|
||||
inline void parseNullTo(JsonVariant &destination);
|
||||
inline void parseNumberTo(JsonVariant &destination);
|
||||
inline const char *parseString();
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
char *_ptr;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
}
|
||||
}
|
54
include/ArduinoJson/Internals/JsonPrintable.hpp
Normal file
54
include/ArduinoJson/Internals/JsonPrintable.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IndentedPrint.hpp"
|
||||
#include "JsonWriter.hpp"
|
||||
#include "Prettyfier.hpp"
|
||||
#include "StringBuilder.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Implements all the overloads of printTo() and prettyPrintTo()
|
||||
// Caution: this class use a template parameter to avoid virtual methods.
|
||||
// This is a bit curious but allows to reduce the size of JsonVariant, JsonArray
|
||||
// and JsonObject.
|
||||
template <typename T>
|
||||
class JsonPrintable {
|
||||
public:
|
||||
size_t printTo(Print &print) const {
|
||||
JsonWriter writer(print);
|
||||
downcast().writeTo(writer);
|
||||
return writer.bytesWritten();
|
||||
}
|
||||
|
||||
size_t printTo(char *buffer, size_t bufferSize) const {
|
||||
StringBuilder sb(buffer, bufferSize);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(IndentedPrint &print) const {
|
||||
Prettyfier p(print);
|
||||
return printTo(p);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
|
||||
StringBuilder sb(buffer, bufferSize);
|
||||
return prettyPrintTo(sb);
|
||||
}
|
||||
|
||||
size_t prettyPrintTo(Print &print) const {
|
||||
IndentedPrint indentedPrint = IndentedPrint(print);
|
||||
return prettyPrintTo(indentedPrint);
|
||||
}
|
||||
|
||||
private:
|
||||
const T &downcast() const { return *static_cast<const T *>(this); }
|
||||
};
|
||||
}
|
||||
}
|
28
include/ArduinoJson/Internals/JsonVariantContent.hpp
Normal file
28
include/ArduinoJson/Internals/JsonVariantContent.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// A union that defines the actual content of a JsonVariant.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
bool asBoolean;
|
||||
double asDouble; // asDouble is also used for float
|
||||
long asLong; // asLong is also used for char, short and int
|
||||
const char* asString; // asString can be null
|
||||
JsonArray* asArray; // asArray cannot be null
|
||||
JsonObject* asObject; // asObject cannot be null
|
||||
};
|
||||
}
|
||||
}
|
33
include/ArduinoJson/Internals/JsonVariantType.hpp
Normal file
33
include/ArduinoJson/Internals/JsonVariantType.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_INVALID, // a special state for JsonVariant::invalid()
|
||||
JSON_UNDEFINED, // the JsonVariant has not been initialized
|
||||
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
|
||||
JSON_BOOLEAN, // the JsonVariant stores a bool
|
||||
JSON_STRING, // the JsonVariant stores a const char*
|
||||
JSON_LONG, // the JsonVariant stores a long
|
||||
|
||||
// The following values are reserved for double values
|
||||
// Multiple values are used for double, depending on the number of decimal
|
||||
// digits that must be printed in the JSON output.
|
||||
// This little trick allow to save one extra member in JsonVariant
|
||||
JSON_DOUBLE_0_DECIMALS
|
||||
// JSON_DOUBLE_1_DECIMAL
|
||||
// JSON_DOUBLE_2_DECIMALS
|
||||
// ...
|
||||
};
|
||||
}
|
||||
}
|
64
include/ArduinoJson/Internals/JsonWriter.hpp
Normal file
64
include/ArduinoJson/Internals/JsonWriter.hpp
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
#include "QuotedString.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Writes the JSON tokens to a Print implementation
|
||||
// This class is used by:
|
||||
// - JsonArray::writeTo()
|
||||
// - JsonObject::writeTo()
|
||||
// - JsonVariant::writeTo()
|
||||
// Its derived by PrettyJsonWriter that overrides some members to add
|
||||
// indentation.
|
||||
class JsonWriter {
|
||||
public:
|
||||
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() { return _length; }
|
||||
|
||||
void beginArray() { write('['); }
|
||||
void endArray() { write(']'); }
|
||||
|
||||
void beginObject() { write('{'); }
|
||||
void endObject() { write('}'); }
|
||||
|
||||
void writeColon() { write(':'); }
|
||||
void writeComma() { write(','); }
|
||||
|
||||
void writeString(const char *value) {
|
||||
_length += QuotedString::printTo(value, _sink);
|
||||
}
|
||||
|
||||
void writeLong(long value) { _length += _sink.print(value); }
|
||||
|
||||
void writeBoolean(bool value) {
|
||||
_length += _sink.print(value ? "true" : "false");
|
||||
}
|
||||
void writeDouble(double value, uint8_t decimals) {
|
||||
_length += _sink.print(value, decimals);
|
||||
}
|
||||
|
||||
protected:
|
||||
void write(char c) { _length += _sink.write(c); }
|
||||
void write(const char *s) { _length += _sink.print(s); }
|
||||
|
||||
Print &_sink;
|
||||
size_t _length;
|
||||
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
};
|
||||
}
|
||||
}
|
74
include/ArduinoJson/Internals/List.hpp
Normal file
74
include/ArduinoJson/Internals/List.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListIterator.hpp"
|
||||
#include "PlacementNew.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A singly linked list of T.
|
||||
// The linked list is composed of ListNode<T>.
|
||||
// It is derived by JsonArray and JsonObject
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ListNode<T> node_type;
|
||||
typedef ListIterator<T> iterator;
|
||||
typedef ListConstIterator<T> const_iterator;
|
||||
|
||||
// Creates an empty List<T> attached to a JsonBuffer.
|
||||
// The JsonBuffer allows to allocate new nodes.
|
||||
// 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) {}
|
||||
|
||||
// Returns true if the object is valid
|
||||
// Would return false in the following situation:
|
||||
// - the memory allocation failed (StaticJsonBuffer was too small)
|
||||
// - the JSON parsing failed
|
||||
bool success() const { return _buffer != NULL; }
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObject, it would return the number of key-value pairs
|
||||
int size() const;
|
||||
|
||||
iterator begin() { return iterator(_firstNode); }
|
||||
iterator end() { return iterator(NULL); }
|
||||
|
||||
const_iterator begin() const { return const_iterator(_firstNode); }
|
||||
const_iterator end() const { return const_iterator(NULL); }
|
||||
|
||||
protected:
|
||||
node_type *createNode() {
|
||||
if (!_buffer) return NULL;
|
||||
void *ptr = _buffer->alloc(sizeof(node_type));
|
||||
return ptr ? new (ptr) node_type() : NULL;
|
||||
}
|
||||
|
||||
void addNode(node_type *nodeToAdd) {
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = nodeToAdd;
|
||||
} else {
|
||||
_firstNode = nodeToAdd;
|
||||
}
|
||||
}
|
||||
|
||||
void removeNode(node_type *nodeToRemove);
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
node_type *_firstNode;
|
||||
};
|
||||
}
|
||||
}
|
40
include/ArduinoJson/Internals/ListConstIterator.hpp
Normal file
40
include/ArduinoJson/Internals/ListConstIterator.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A read-only forward itertor for List<T>
|
||||
template <typename T>
|
||||
class ListConstIterator {
|
||||
public:
|
||||
explicit ListConstIterator(const ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
const T &operator*() const { return _node->content; }
|
||||
const T *operator->() { return &_node->content; }
|
||||
|
||||
bool operator==(const ListConstIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListConstIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
40
include/ArduinoJson/Internals/ListIterator.hpp
Normal file
40
include/ArduinoJson/Internals/ListIterator.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A read-write forward iterator for List<T>
|
||||
template <typename T>
|
||||
class ListIterator {
|
||||
public:
|
||||
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
T &operator*() const { return _node->content; }
|
||||
T *operator->() { return &_node->content; }
|
||||
|
||||
bool operator==(const ListIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
ListNode<T> *_node;
|
||||
};
|
||||
}
|
||||
}
|
24
include/ArduinoJson/Internals/ListNode.hpp
Normal file
24
include/ArduinoJson/Internals/ListNode.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for NULL
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A node for a singly-linked list.
|
||||
// Used by List<T> and its iterators.
|
||||
template <typename T>
|
||||
struct ListNode {
|
||||
ListNode() : next(NULL) {}
|
||||
|
||||
ListNode<T>* next;
|
||||
T content;
|
||||
};
|
||||
}
|
||||
}
|
19
include/ArduinoJson/Internals/PlacementNew.hpp
Normal file
19
include/ArduinoJson/Internals/PlacementNew.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
// Declares the placement new as in <new>.
|
||||
// This is required for Arduino IDE because it doesn't include the <new> header.
|
||||
inline void *operator new(size_t, void *p) throw() { return p; }
|
||||
|
||||
#else
|
||||
|
||||
#include <new>
|
||||
|
||||
#endif
|
46
include/ArduinoJson/Internals/Prettyfier.hpp
Normal file
46
include/ArduinoJson/Internals/Prettyfier.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IndentedPrint.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Converts a compact JSON string into an indented one.
|
||||
class Prettyfier : public Print {
|
||||
public:
|
||||
explicit Prettyfier(IndentedPrint& p) : _sink(p) {
|
||||
_previousChar = 0;
|
||||
_inString = false;
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
|
||||
private:
|
||||
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
|
||||
|
||||
bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; }
|
||||
|
||||
size_t handleStringChar(uint8_t);
|
||||
size_t handleMarkupChar(uint8_t);
|
||||
|
||||
size_t handleBlockClose(uint8_t);
|
||||
size_t handleBlockOpen(uint8_t);
|
||||
size_t handleColumn();
|
||||
size_t handleComma();
|
||||
size_t handleQuoteOpen();
|
||||
size_t handleNormalChar(uint8_t);
|
||||
size_t indentIfNeeded();
|
||||
size_t unindentIfNeeded();
|
||||
|
||||
uint8_t _previousChar;
|
||||
IndentedPrint& _sink;
|
||||
bool _inString;
|
||||
};
|
||||
}
|
||||
}
|
29
include/ArduinoJson/Internals/QuotedString.hpp
Normal file
29
include/ArduinoJson/Internals/QuotedString.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// An helper class to print and extract doubly-quoted strings
|
||||
class QuotedString {
|
||||
public:
|
||||
// Writes a doubly-quote string to a Print implementation.
|
||||
// It adds the double quotes (") at the beginning and the end of the string.
|
||||
// It escapes the special characters as required by the JSON specifications.
|
||||
static size_t printTo(const char *, Print &);
|
||||
|
||||
// Reads a doubly-quoted string from a buffer.
|
||||
// It removes the double quotes (").
|
||||
// It unescapes the special character as required by the JSON specification,
|
||||
// with the exception of the Unicode characters (\u0000).
|
||||
static char *extractFrom(char *input, char **end);
|
||||
};
|
||||
}
|
||||
}
|
34
include/ArduinoJson/Internals/ReferenceType.hpp
Normal file
34
include/ArduinoJson/Internals/ReferenceType.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that is meant to be used by reference only (JsonArray and JsonObject)
|
||||
class ReferenceType {
|
||||
public:
|
||||
bool operator==(const ReferenceType& other) const {
|
||||
// two JsonArray are equal if they are the same instance
|
||||
// (we don't compare the content)
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
bool operator!=(const ReferenceType& other) const { return this != &other; }
|
||||
|
||||
protected:
|
||||
ReferenceType() {}
|
||||
|
||||
private:
|
||||
// copy constructor is private
|
||||
ReferenceType(const ReferenceType&);
|
||||
|
||||
// copy operator is private
|
||||
ReferenceType& operator=(const ReferenceType&);
|
||||
};
|
||||
}
|
||||
}
|
30
include/ArduinoJson/Internals/StringBuilder.hpp
Normal file
30
include/ArduinoJson/Internals/StringBuilder.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Arduino/Print.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A Print implementation that allows to write in a char[]
|
||||
class StringBuilder : public Print {
|
||||
public:
|
||||
StringBuilder(char *buf, int size)
|
||||
: buffer(buf), capacity(size - 1), length(0) {
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t c);
|
||||
|
||||
private:
|
||||
char *buffer;
|
||||
int capacity;
|
||||
int length;
|
||||
};
|
||||
}
|
||||
}
|
88
include/ArduinoJson/JsonArray.hpp
Normal file
88
include/ArduinoJson/JsonArray.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an array with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonObject;
|
||||
class JsonBuffer;
|
||||
|
||||
// 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,
|
||||
public Internals::List<JsonVariant> {
|
||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
||||
friend class JsonBuffer;
|
||||
|
||||
public:
|
||||
// Returns the JsonVariant at the specified index (synonym for operator[])
|
||||
JsonVariant &at(int index) const;
|
||||
|
||||
// Returns the JsonVariant at the specified index (synonym for at())
|
||||
JsonVariant &operator[](int index) const { return at(index); }
|
||||
|
||||
// Adds an uninitialized JsonVariant at the end of the array.
|
||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
||||
JsonVariant &add();
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
template <typename T>
|
||||
void add(T value) {
|
||||
add().set(value);
|
||||
}
|
||||
|
||||
// Adds the specified double value at the end of the array.
|
||||
// The value will be printed with the specified number of decimal digits.
|
||||
void add(double value, uint8_t decimals) { add().set(value, decimals); }
|
||||
|
||||
// Adds a reference to the specified JsonArray at the end of the array.
|
||||
void add(JsonArray &array) { add().set(array); }
|
||||
|
||||
// Adds a reference to the specified JsonObject at the end of the array.
|
||||
void add(JsonObject &obejct) { add().set(obejct); }
|
||||
|
||||
// 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();
|
||||
|
||||
// Returns a reference an invalid JsonArray.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonArray &invalid() { return _invalid; }
|
||||
|
||||
// Serialize the array to the specified JsonWriter.
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
private:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
explicit JsonArray(JsonBuffer *buffer)
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
|
||||
// The instance returned by JsonArray::invalid()
|
||||
static JsonArray _invalid;
|
||||
};
|
||||
}
|
81
include/ArduinoJson/JsonBuffer.hpp
Normal file
81
include/ArduinoJson/JsonBuffer.hpp
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// Entry point for using the library.
|
||||
//
|
||||
// Handle the memory management (done in derived classes) and calls the parser.
|
||||
// This abstract class is implemented by StaticJsonBuffer which implements a
|
||||
// fixed memory allocation.
|
||||
class JsonBuffer {
|
||||
public:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc() and
|
||||
// free() to the binary, adding 706 useless bytes.
|
||||
// virtual ~JsonBuffer() {}
|
||||
|
||||
// Allocates an empty JsonArray.
|
||||
//
|
||||
// Returns a reference to the new JsonArray or JsonArray::invalid() if the
|
||||
// allocation fails.
|
||||
JsonArray &createArray();
|
||||
|
||||
// Allocates an empty JsonObject.
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
JsonObject &createObject();
|
||||
|
||||
// Allocates and populate a JsonArray from a JSON string.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
// writable
|
||||
// because the parser will insert null-terminators and replace escaped chars.
|
||||
//
|
||||
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||
|
||||
// Allocates and populate a JsonObject from a JSON string.
|
||||
//
|
||||
// The First argument is a pointer to the JSON string, the memory must be
|
||||
// writable
|
||||
// because the parser will insert null-terminators and replace escaped chars.
|
||||
//
|
||||
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
|
||||
//
|
||||
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
|
||||
// allocation fails.
|
||||
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||
|
||||
// Allocates n bytes in the JsonBuffer.
|
||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
||||
// Default value of nesting limit of parseArray() and parseObject().
|
||||
//
|
||||
// The nesting limit is a contain on the level of nesting allowed in the JSON
|
||||
// string.
|
||||
// If set to 0, only a flat array or objects can be parsed.
|
||||
// If set to 1, the object can contain nested arrays or objects but only 1
|
||||
// level deep.
|
||||
// And bigger values will allow more level of nesting.
|
||||
//
|
||||
// The purpose of this feature is to prevent stack overflow that could lead to
|
||||
// a security risk.
|
||||
static const uint8_t DEFAULT_LIMIT = 10;
|
||||
};
|
||||
}
|
105
include/ArduinoJson/JsonObject.hpp
Normal file
105
include/ArduinoJson/JsonObject.hpp
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/List.hpp"
|
||||
#include "Internals/ReferenceType.hpp"
|
||||
#include "JsonPair.hpp"
|
||||
|
||||
// Returns the size (in bytes) of an object with n elements.
|
||||
// Can be very handy to determine the size of a StaticJsonBuffer.
|
||||
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
|
||||
(sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type))
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonBuffer;
|
||||
|
||||
// A dictionary of JsonVariant indexed by string (char*)
|
||||
//
|
||||
// The constructor is private, instances must be created via
|
||||
// JsonBuffer::createObject() or JsonBuffer::parseObject().
|
||||
// A JsonObject can be serialized to a JSON string via JsonObject::printTo().
|
||||
// It can also be deserialized from a JSON string via JsonBuffer::parseObject().
|
||||
class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
public Internals::ReferenceType,
|
||||
public Internals::List<JsonPair> {
|
||||
// JsonBuffer is a friend because it needs to call the private constructor.
|
||||
friend class JsonBuffer;
|
||||
|
||||
public:
|
||||
typedef const char *key_type;
|
||||
typedef JsonPair value_type;
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a reference or JsonVariant::invalid() if not found.
|
||||
JsonVariant &at(key_type key);
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
||||
const JsonVariant &at(key_type key) const;
|
||||
|
||||
// Gets or create the JsonVariant associated with the specified key.
|
||||
// Returns a reference or JsonVariant::invalid() if allocation failed.
|
||||
JsonVariant &operator[](key_type key);
|
||||
|
||||
// Gets the JsonVariant associated with the specified key.
|
||||
// Returns a constant reference or JsonVariant::invalid() if not found.
|
||||
const JsonVariant &operator[](key_type key) const { return at(key); }
|
||||
|
||||
// Adds an uninitialized JsonVariant associated with the specified key.
|
||||
// Return a reference or JsonVariant::invalid() if allocation fails.
|
||||
JsonVariant &add(key_type key) { return (*this)[key]; }
|
||||
|
||||
// Adds the specified key with the specified value.
|
||||
template <typename T>
|
||||
void add(key_type key, T value) {
|
||||
add(key).set(value);
|
||||
}
|
||||
|
||||
// Adds the specified key with a reference to the specified JsonArray.
|
||||
void add(key_type key, JsonArray &array) { add(key).set(array); }
|
||||
|
||||
// Adds the specified key with a reference to the specified JsonObject.
|
||||
void add(key_type key, JsonObject &object) { add(key).set(object); }
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||
JsonArray &createNestedArray(key_type key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||
JsonObject &createNestedObject(key_type key);
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
bool containsKey(key_type key) const { return at(key).success(); }
|
||||
|
||||
// Removes the specified key and the associated value.
|
||||
void remove(key_type key);
|
||||
|
||||
// Returns a reference an invalid JsonObject.
|
||||
// This object is meant to replace a NULL pointer.
|
||||
// This is used when memory allocation or JSON parsing fail.
|
||||
static JsonObject &invalid() { return _invalid; }
|
||||
|
||||
// Serialize the object to the specified JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
private:
|
||||
// Create an empty JsonArray attached to the specified JsonBuffer.
|
||||
explicit JsonObject(JsonBuffer *buffer) : Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Returns the list node that matches the specified key.
|
||||
node_type *getNodeAt(key_type key) const;
|
||||
|
||||
// The instance returned by JsonObject::invalid()
|
||||
static JsonObject _invalid;
|
||||
};
|
||||
}
|
18
include/ArduinoJson/JsonPair.hpp
Normal file
18
include/ArduinoJson/JsonPair.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// A key value pair for JsonObject.
|
||||
struct JsonPair {
|
||||
const char* key;
|
||||
JsonVariant value;
|
||||
};
|
||||
}
|
286
include/ArduinoJson/JsonVariant.hpp
Normal file
286
include/ArduinoJson/JsonVariant.hpp
Normal file
@ -0,0 +1,286 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/JsonVariantContent.hpp"
|
||||
#include "Internals/JsonVariantType.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
// A variant that can be a any value serializable to a JSON value.
|
||||
//
|
||||
// It can be set to:
|
||||
// - a boolean
|
||||
// - a char, short, int or a long (signed or unsigned)
|
||||
// - a string (const char*)
|
||||
// - a reference to a JsonArray or JsonObject
|
||||
class JsonVariant : public Internals::JsonPrintable<JsonVariant> {
|
||||
public:
|
||||
// Creates an uninitialized JsonVariant
|
||||
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
|
||||
|
||||
// Initializes a JsonVariant with the specified value.
|
||||
template <typename T>
|
||||
explicit JsonVariant(T value) {
|
||||
set(value);
|
||||
}
|
||||
|
||||
// Tells weither the variant is valid.
|
||||
bool success() const {
|
||||
return _type != Internals::JSON_INVALID &&
|
||||
_type != Internals::JSON_UNDEFINED;
|
||||
}
|
||||
|
||||
// Sets the variant to a boolean value.
|
||||
// It will be serialized as "true" or "false" in JSON.
|
||||
void set(bool value);
|
||||
|
||||
// Sets the variant to a floating point value.
|
||||
// The second argument specifies the number of decimal digits to write in
|
||||
// the JSON string.
|
||||
void set(double value, uint8_t decimals = 2);
|
||||
|
||||
// Sets the variant to be an integer value.
|
||||
void set(signed long value);
|
||||
void set(signed char value) { set(static_cast<long>(value)); }
|
||||
void set(signed int value) { set(static_cast<long>(value)); }
|
||||
void set(signed short value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned char value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned int value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned long value) { set(static_cast<long>(value)); }
|
||||
void set(unsigned short value) { set(static_cast<long>(value)); }
|
||||
|
||||
// Sets the variant to be a string.
|
||||
void set(const char *value);
|
||||
|
||||
// Sets the variant to be a reference to an array.
|
||||
void set(JsonArray &array);
|
||||
|
||||
// Sets the variant to be a reference to an object.
|
||||
void set(JsonObject &object);
|
||||
|
||||
// Sets the variant to the specified value.
|
||||
template <typename T>
|
||||
JsonVariant &operator=(T value) {
|
||||
set(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the variant to be a reference to an array.
|
||||
JsonVariant &operator=(JsonArray &array) {
|
||||
set(array);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Sets the variant to be a reference to an object.
|
||||
JsonVariant &operator=(JsonObject &object) {
|
||||
set(object);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Gets the variant as a boolean value.
|
||||
// Returns false if the variant is not a boolean value.
|
||||
operator bool() const;
|
||||
|
||||
// Gets the variant as a floating-point value.
|
||||
// Returns 0.0 if the variant is not a floating-point value
|
||||
operator double() const;
|
||||
operator float() const { return static_cast<float>(as<double>()); }
|
||||
|
||||
// Gets the variant as an integer value.
|
||||
// Returns 0 if the variant is not an integer value.
|
||||
operator signed long() const;
|
||||
operator signed char() const { return cast_long_to<signed char>(); }
|
||||
operator signed int() const { return cast_long_to<signed int>(); }
|
||||
operator signed short() const { return cast_long_to<signed short>(); }
|
||||
operator unsigned char() const { return cast_long_to<unsigned char>(); }
|
||||
operator unsigned int() const { return cast_long_to<unsigned int>(); }
|
||||
operator unsigned long() const { return cast_long_to<unsigned long>(); }
|
||||
operator unsigned short() const { return cast_long_to<unsigned short>(); }
|
||||
|
||||
// Gets the variant as a string.
|
||||
// Returns NULL if variant is not a string.
|
||||
operator const char *() const;
|
||||
const char *asString() const { return as<const char *>(); }
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the variant
|
||||
// is not an array.
|
||||
operator JsonArray &() const;
|
||||
JsonArray &asArray() const { return as<JsonArray &>(); }
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
operator JsonObject &() const;
|
||||
JsonObject &asObject() const { return as<JsonObject &>(); }
|
||||
|
||||
// Get the variant as the specified type.
|
||||
// See cast operators for details.
|
||||
template <typename T>
|
||||
T as() const {
|
||||
return static_cast<T>(*this);
|
||||
}
|
||||
|
||||
// Tells weither the variant has the specified type.
|
||||
// Returns true if the variant has type type T, false otherwise.
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns an invalid variant.
|
||||
// This is meant to replace a NULL pointer.
|
||||
static JsonVariant &invalid() { return _invalid; }
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const;
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
JsonVariant &operator[](int index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is an
|
||||
// object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
JsonVariant &operator[](const char *key);
|
||||
|
||||
private:
|
||||
// Special constructor used only to create _invalid.
|
||||
explicit JsonVariant(Internals::JsonVariantType type) : _type(type) {}
|
||||
|
||||
// Helper for interger cast operators
|
||||
template <typename T>
|
||||
T cast_long_to() const {
|
||||
return static_cast<T>(as<long>());
|
||||
}
|
||||
|
||||
// The current type of the variant
|
||||
Internals::JsonVariantType _type;
|
||||
|
||||
// The various alternatives for the value of the variant.
|
||||
Internals::JsonVariantContent _content;
|
||||
|
||||
// The instance returned by JsonVariant::invalid()
|
||||
static JsonVariant _invalid;
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<long>() const {
|
||||
return _type == Internals::JSON_LONG;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<double>() const {
|
||||
return _type >= Internals::JSON_DOUBLE_0_DECIMALS;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<bool>() const {
|
||||
return _type == Internals::JSON_BOOLEAN;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const char *>() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const JsonArray &>() const {
|
||||
return _type == Internals::JSON_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<const JsonObject &>() const {
|
||||
return _type == Internals::JSON_OBJECT;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(const JsonVariant &left, T right) {
|
||||
return left.as<T>() == right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator==(T left, const JsonVariant &right) {
|
||||
return left == right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() != right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator!=(T left, const JsonVariant &right) {
|
||||
return left != right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() <= right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<=(T left, const JsonVariant &right) {
|
||||
return left <= right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>=(const JsonVariant &left, T right) {
|
||||
return left.as<T>() >= right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>=(T left, const JsonVariant &right) {
|
||||
return left >= right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<(const JsonVariant &left, T right) {
|
||||
return left.as<T>() < right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator<(T left, const JsonVariant &right) {
|
||||
return left < right.as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>(const JsonVariant &left, T right) {
|
||||
return left.as<T>() > right;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool operator>(T left, const JsonVariant &right) {
|
||||
return left > right.as<T>();
|
||||
}
|
||||
}
|
36
include/ArduinoJson/StaticJsonBuffer.hpp
Normal file
36
include/ArduinoJson/StaticJsonBuffer.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Implements a JsonBuffer with fixed memory allocation.
|
||||
// The template paramenter CAPACITY specifies the capacity of the buffer in
|
||||
// bytes.
|
||||
template <size_t CAPACITY>
|
||||
class StaticJsonBuffer : public JsonBuffer {
|
||||
public:
|
||||
explicit StaticJsonBuffer() : _size(0) {}
|
||||
|
||||
size_t capacity() const { return CAPACITY; }
|
||||
size_t size() const { return _size; }
|
||||
|
||||
protected:
|
||||
virtual void* alloc(size_t size) {
|
||||
if (_size + size > CAPACITY) return NULL;
|
||||
void* p = &_buffer[_size];
|
||||
_size += size;
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _buffer[CAPACITY];
|
||||
size_t _size;
|
||||
};
|
||||
}
|
20
keywords.txt
20
keywords.txt
@ -1,10 +1,14 @@
|
||||
JsonParser KEYWORD1
|
||||
JsonArray KEYWORD1
|
||||
JsonHashTable KEYWORD1
|
||||
getArray KEYWORD2
|
||||
getBool KEYWORD2
|
||||
getDouble KEYWORD2
|
||||
getHashTableKEYWORD2
|
||||
getLong KEYWORD2
|
||||
JsonObject KEYWORD1
|
||||
JsonVariant KEYWORD1
|
||||
StaticJsonBuffer KEYWORD1
|
||||
add KEYWORD2
|
||||
createArray KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
createNestedObject KEYWORD2
|
||||
createObject KEYWORD2
|
||||
parseArray KEYWORD2
|
||||
parseHashTable KEYWORD2
|
||||
parseObject KEYWORD2
|
||||
prettyPrintTo KEYWORD2
|
||||
printTo KEYWORD2
|
||||
success KEYWORD2
|
||||
|
17
library.json
Normal file
17
library.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Json",
|
||||
"keywords": "json, rest, http, web",
|
||||
"description": "An elegant and efficient JSON library for embedded systems",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"authors":
|
||||
{
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "http://blog.benoitblanchon.fr"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "atmelavr"
|
||||
}
|
8
library.properties
Normal file
8
library.properties
Normal file
@ -0,0 +1,8 @@
|
||||
name=ArduinoJson
|
||||
version=4.0
|
||||
author=Benoit Blanchon <http://blog.benoitblanchon.fr/>
|
||||
maintainer=Benoit Blanchon <http://blog.benoitblanchon.fr/>
|
||||
sentence=An efficient and elegant JSON library for Arduino
|
||||
paragraph=Supports JSON parsing and formatting. Uses fixed memory allocation.
|
||||
url=https://github.com/bblanchon/ArduinoJson
|
||||
architectures=*
|
22
scripts/build-arduino-package.sh
Executable file
22
scripts/build-arduino-package.sh
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
ZIP="C:\Program Files\7-Zip\7z.exe"
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG.zip"
|
||||
|
||||
cd ../..
|
||||
|
||||
# remove existing file
|
||||
rm -f $OUTPUT
|
||||
|
||||
# create zip
|
||||
"$ZIP" a $OUTPUT \
|
||||
ArduinoJson/CHANGELOG.md \
|
||||
ArduinoJson/doc \
|
||||
ArduinoJson/examples \
|
||||
ArduinoJson/include \
|
||||
ArduinoJson/keywords.txt \
|
||||
ArduinoJson/library.properties \
|
||||
ArduinoJson/LICENSE.md \
|
||||
ArduinoJson/README.md \
|
||||
ArduinoJson/src
|
5
scripts/cpplint.sh
Executable file
5
scripts/cpplint.sh
Executable file
@ -0,0 +1,5 @@
|
||||
CPPLINT="python third-party/cpplint/cpplint.py"
|
||||
FLAGS="--filter=-runtime/printf,-runtime/int,-readability/todo,-build/namespace,-runtime/references,-readability/streams"
|
||||
|
||||
cd ..
|
||||
$CPPLINT $FLAGS $(find include src test -regex ".*\.[hc]pp$")
|
29
scripts/create-build-envs.sh
Executable file
29
scripts/create-build-envs.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
export PATH="$PATH:/Applications/CMake.app/Contents/bin/"
|
||||
|
||||
cd $(dirname $0)/..
|
||||
ROOT=$(pwd)
|
||||
|
||||
mkdir "build"
|
||||
cd build
|
||||
BUILD=$(pwd)
|
||||
|
||||
build-env()
|
||||
{
|
||||
cd $BUILD
|
||||
mkdir "$1"
|
||||
cd "$1"
|
||||
cmake "$ROOT" -G "$2"
|
||||
}
|
||||
|
||||
if [[ $(uname) == MINGW* ]]
|
||||
then
|
||||
build-env "Make" "MinGW Makefiles"
|
||||
build-env "SublimeText" "Sublime Text 2 - MinGW Makefiles"
|
||||
build-env "VisualStudio" "Visual Studio 12 2013"
|
||||
else
|
||||
build-env "SublimeText" "Sublime Text 2 - Unix Makefiles"
|
||||
build-env "Make" "Unix Makefiles"
|
||||
build-env "Xcode" "Xcode"
|
||||
fi
|
7
scripts/format-code.sh
Executable file
7
scripts/format-code.sh
Executable file
@ -0,0 +1,7 @@
|
||||
cd ..
|
||||
FILES=$(find include src test -regex ".*\.[ch]pp$")
|
||||
|
||||
clang-format -style=Google -i $FILES
|
||||
|
||||
# insert newline at end of file
|
||||
sed -i -e '$a\' $FILES
|
44
scripts/run-tests.sh
Executable file
44
scripts/run-tests.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
FILE=../bin/ArduinoJsonTests.exe
|
||||
MD5=""
|
||||
|
||||
file_changed() {
|
||||
[[ ! -f "$FILE" ]] && return 1
|
||||
NEW_MD5=$(md5sum $FILE)
|
||||
[[ "$MD5" == "$NEW_MD5" ]] && return 1
|
||||
MD5=$NEW_MD5
|
||||
return 0
|
||||
}
|
||||
|
||||
test_succeed() {
|
||||
echo -en "\007"{,}
|
||||
}
|
||||
|
||||
test_failed() {
|
||||
echo -en "\007"{,,,,,,,,,,,}
|
||||
}
|
||||
|
||||
run_tests() {
|
||||
$FILE
|
||||
case $? in
|
||||
0)
|
||||
test_succeed
|
||||
;;
|
||||
1)
|
||||
test_failed
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
while true
|
||||
do
|
||||
if file_changed
|
||||
then
|
||||
run_tests
|
||||
else
|
||||
sleep 2
|
||||
fi
|
||||
done
|
||||
|
||||
|
35
src/Arduino/Print.cpp
Normal file
35
src/Arduino/Print.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include "../../include/ArduinoJson/Arduino/Print.hpp"
|
||||
|
||||
#include <stdio.h> // for sprintf
|
||||
|
||||
size_t Print::print(const char s[]) {
|
||||
size_t n = 0;
|
||||
while (*s) {
|
||||
n += write(*s++);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(double value, int digits) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%.*f", digits, value);
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
size_t Print::print(long value) {
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%ld", value);
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
size_t Print::println() { return write('\r') + write('\n'); }
|
||||
|
||||
#endif
|
13
src/ArduinoJson.h
Normal file
13
src/ArduinoJson.h
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
// About this file
|
||||
// ---------------
|
||||
// This file is here to please the Arduino IDE. It must be present in the src/
|
||||
// for the IDE to find it. Feel free to ignore this file if your working in
|
||||
// another environment
|
||||
|
||||
#include "../include/ArduinoJson.h"
|
42
src/CMakeLists.txt
Normal file
42
src/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
file(GLOB_RECURSE INC_FILES ../include/*.hpp)
|
||||
file(GLOB_RECURSE SRC_FILES *.cpp)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
add_definitions(
|
||||
-fno-exceptions
|
||||
-pedantic
|
||||
-Wall
|
||||
-Wcast-align
|
||||
-Wcast-qual
|
||||
-Wconversion
|
||||
-Wctor-dtor-privacy
|
||||
-Wdisabled-optimization
|
||||
-Werror
|
||||
-Wextra
|
||||
-Wformat=2
|
||||
-Winit-self
|
||||
-Wmissing-include-dirs
|
||||
-Wno-parentheses
|
||||
-Wno-sign-conversion
|
||||
-Wno-unused
|
||||
-Wno-variadic-macros
|
||||
-Wold-style-cast
|
||||
-Woverloaded-virtual
|
||||
-Wredundant-decls
|
||||
-Wshadow
|
||||
-Wsign-promo
|
||||
-Wstrict-overflow=5
|
||||
-Wundef
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU)")
|
||||
add_definitions(
|
||||
-Wlogical-op
|
||||
-Wnoexcept
|
||||
-Wstrict-null-sentinel
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
add_library(ArduinoJson ${SRC_FILES} ${INC_FILES})
|
29
src/Internals/IndentedPrint.cpp
Normal file
29
src/Internals/IndentedPrint.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/IndentedPrint.hpp"
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
size_t IndentedPrint::write(uint8_t c) {
|
||||
size_t n = 0;
|
||||
|
||||
if (isNewLine) n += writeTabs();
|
||||
|
||||
n += sink->write(c);
|
||||
|
||||
isNewLine = c == '\n';
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
inline size_t IndentedPrint::writeTabs() {
|
||||
size_t n = 0;
|
||||
|
||||
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
|
||||
|
||||
return n;
|
||||
}
|
197
src/Internals/JsonParser.cpp
Normal file
197
src/Internals/JsonParser.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/JsonParser.hpp"
|
||||
|
||||
#include <stdlib.h> // for strtol, strtod
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
|
||||
#include "../../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../../include/ArduinoJson/JsonBuffer.hpp"
|
||||
#include "../../include/ArduinoJson/JsonObject.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
void JsonParser::skipSpaces() {
|
||||
while (isspace(*_ptr)) _ptr++;
|
||||
}
|
||||
|
||||
bool JsonParser::skip(char charToSkip) {
|
||||
skipSpaces();
|
||||
if (*_ptr != charToSkip) return false;
|
||||
_ptr++;
|
||||
skipSpaces();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonParser::skip(const char *wordToSkip) {
|
||||
const char *charToSkip = wordToSkip;
|
||||
while (*charToSkip && *_ptr == *charToSkip) {
|
||||
charToSkip++;
|
||||
_ptr++;
|
||||
}
|
||||
return *charToSkip == '\0';
|
||||
}
|
||||
|
||||
void JsonParser::parseAnythingTo(JsonVariant &destination) {
|
||||
if (_nestingLimit == 0) return;
|
||||
_nestingLimit--;
|
||||
|
||||
skipSpaces();
|
||||
|
||||
switch (*_ptr) {
|
||||
case '[':
|
||||
destination = parseArray();
|
||||
break;
|
||||
|
||||
case '{':
|
||||
destination = parseObject();
|
||||
break;
|
||||
|
||||
case 't':
|
||||
case 'f':
|
||||
parseBooleanTo(destination);
|
||||
break;
|
||||
|
||||
case '-':
|
||||
case '.':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
parseNumberTo(destination);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
parseNullTo(destination);
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
case '\"':
|
||||
destination = parseString();
|
||||
break;
|
||||
}
|
||||
|
||||
_nestingLimit++;
|
||||
}
|
||||
|
||||
JsonArray &JsonParser::parseArray() {
|
||||
// Create an empty array
|
||||
JsonArray &array = _buffer->createArray();
|
||||
|
||||
// Check opening braket
|
||||
if (!skip('[')) goto ERROR_MISSING_BRACKET;
|
||||
if (skip(']')) goto SUCCESS_EMPTY_ARRAY;
|
||||
|
||||
// Read each value
|
||||
for (;;) {
|
||||
// 1 - Parse value
|
||||
JsonVariant &value = array.add();
|
||||
parseAnythingTo(value);
|
||||
if (!value.success()) goto ERROR_INVALID_VALUE;
|
||||
|
||||
// 2 - More values?
|
||||
if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY;
|
||||
if (!skip(',')) goto ERROR_MISSING_COMMA;
|
||||
}
|
||||
|
||||
SUCCESS_EMPTY_ARRAY:
|
||||
SUCCES_NON_EMPTY_ARRAY:
|
||||
return array;
|
||||
|
||||
ERROR_INVALID_VALUE:
|
||||
ERROR_MISSING_BRACKET:
|
||||
ERROR_MISSING_COMMA:
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
JsonObject &JsonParser::parseObject() {
|
||||
// Create an empty object
|
||||
JsonObject &object = _buffer->createObject();
|
||||
|
||||
// Check opening brace
|
||||
if (!skip('{')) goto ERROR_MISSING_BRACE;
|
||||
if (skip('}')) goto SUCCESS_EMPTY_OBJECT;
|
||||
|
||||
// Read each key value pair
|
||||
for (;;) {
|
||||
// 1 - Parse key
|
||||
const char *key = parseString();
|
||||
if (!key) goto ERROR_INVALID_KEY;
|
||||
if (!skip(':')) goto ERROR_MISSING_COLON;
|
||||
|
||||
// 2 - Parse value
|
||||
JsonVariant &value = object.add(key);
|
||||
parseAnythingTo(value);
|
||||
if (!value.success()) goto ERROR_INVALID_VALUE;
|
||||
|
||||
// 3 - More keys/values?
|
||||
if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT;
|
||||
if (!skip(',')) 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:
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
void JsonParser::parseBooleanTo(JsonVariant &destination) {
|
||||
if (skip("true"))
|
||||
destination = true;
|
||||
else if (skip("false"))
|
||||
destination = false;
|
||||
else
|
||||
destination = JsonVariant::invalid();
|
||||
}
|
||||
|
||||
void JsonParser::parseNumberTo(JsonVariant &destination) {
|
||||
char *endOfLong;
|
||||
long longValue = strtol(_ptr, &endOfLong, 10);
|
||||
char stopChar = *endOfLong;
|
||||
|
||||
// Could it be a floating point value?
|
||||
bool couldBeFloat = stopChar == '.' || stopChar == 'e' || stopChar == 'E';
|
||||
|
||||
if (couldBeFloat) {
|
||||
// Yes => parse it as a double
|
||||
double doubleValue = strtod(_ptr, &_ptr);
|
||||
// Count the decimal digits
|
||||
uint8_t decimals = static_cast<uint8_t>(_ptr - endOfLong - 1);
|
||||
// Set the variant as a double
|
||||
destination.set(doubleValue, decimals);
|
||||
} else {
|
||||
// No => set the variant as a long
|
||||
_ptr = endOfLong;
|
||||
destination = longValue;
|
||||
}
|
||||
}
|
||||
|
||||
void JsonParser::parseNullTo(JsonVariant &destination) {
|
||||
const char *NULL_STRING = NULL;
|
||||
if (skip("null"))
|
||||
destination = NULL_STRING;
|
||||
else
|
||||
destination = JsonVariant::invalid();
|
||||
}
|
||||
|
||||
const char *JsonParser::parseString() {
|
||||
return QuotedString::extractFrom(_ptr, &_ptr);
|
||||
}
|
35
src/Internals/List.cpp
Normal file
35
src/Internals/List.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/List.hpp"
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/PlacementNew.hpp"
|
||||
#include "../../include/ArduinoJson/JsonPair.hpp"
|
||||
#include "../../include/ArduinoJson/JsonVariant.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
template <typename T>
|
||||
int List<T>::size() const {
|
||||
int nodeCount = 0;
|
||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void List<T>::removeNode(node_type *nodeToRemove) {
|
||||
if (!nodeToRemove) return;
|
||||
if (nodeToRemove == _firstNode) {
|
||||
_firstNode = nodeToRemove->next;
|
||||
} else {
|
||||
for (node_type *node = _firstNode; node; node = node->next)
|
||||
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
|
||||
}
|
||||
}
|
||||
|
||||
template class List<JsonPair>;
|
||||
template class List<JsonVariant>;
|
86
src/Internals/Prettyfier.cpp
Normal file
86
src/Internals/Prettyfier.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/Prettyfier.hpp"
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
size_t Prettyfier::write(uint8_t c) {
|
||||
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(c);
|
||||
_previousChar = c;
|
||||
return n;
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleStringChar(uint8_t c) {
|
||||
bool isQuote = c == '"' && _previousChar != '\\';
|
||||
|
||||
if (isQuote) _inString = false;
|
||||
|
||||
return _sink.write(c);
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleMarkupChar(uint8_t c) {
|
||||
switch (c) {
|
||||
case '{':
|
||||
case '[':
|
||||
return handleBlockOpen(c);
|
||||
|
||||
case '}':
|
||||
case ']':
|
||||
return handleBlockClose(c);
|
||||
|
||||
case ':':
|
||||
return handleColumn();
|
||||
|
||||
case ',':
|
||||
return handleComma();
|
||||
|
||||
case '"':
|
||||
return handleQuoteOpen();
|
||||
|
||||
default:
|
||||
return handleNormalChar(c);
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleBlockOpen(uint8_t c) {
|
||||
return indentIfNeeded() + _sink.write(c);
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleBlockClose(uint8_t c) {
|
||||
return unindentIfNeeded() + _sink.write(c);
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleColumn() {
|
||||
return _sink.write(':') + _sink.write(' ');
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleComma() {
|
||||
return _sink.write(',') + _sink.println();
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleQuoteOpen() {
|
||||
_inString = true;
|
||||
return indentIfNeeded() + _sink.write('"');
|
||||
}
|
||||
|
||||
inline size_t Prettyfier::handleNormalChar(uint8_t c) {
|
||||
return indentIfNeeded() + _sink.write(c);
|
||||
}
|
||||
|
||||
size_t Prettyfier::indentIfNeeded() {
|
||||
if (!inEmptyBlock()) return 0;
|
||||
|
||||
_sink.indent();
|
||||
return _sink.println();
|
||||
}
|
||||
|
||||
size_t Prettyfier::unindentIfNeeded() {
|
||||
if (inEmptyBlock()) return 0;
|
||||
|
||||
_sink.unindent();
|
||||
return _sink.println();
|
||||
}
|
98
src/Internals/QuotedString.cpp
Normal file
98
src/Internals/QuotedString.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
static inline char getSpecialChar(char c) {
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
|
||||
const char *p = "\"\"\\\\\bb\ff\nn\rr\tt\0";
|
||||
|
||||
while (p[0] && p[0] != c) {
|
||||
p += 2;
|
||||
}
|
||||
|
||||
return p[1];
|
||||
}
|
||||
|
||||
static inline size_t printCharTo(char c, Print &p) {
|
||||
char specialChar = getSpecialChar(c);
|
||||
|
||||
return specialChar ? p.write('\\') + p.write(specialChar) : p.write(c);
|
||||
}
|
||||
|
||||
size_t QuotedString::printTo(const char *s, Print &p) {
|
||||
if (!s) return p.print("null");
|
||||
|
||||
size_t n = p.write('\"');
|
||||
|
||||
while (*s) {
|
||||
n += printCharTo(*s++, p);
|
||||
}
|
||||
|
||||
return n + p.write('\"');
|
||||
}
|
||||
|
||||
static char unescapeChar(char c) {
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
|
||||
const char *p = "b\bf\fn\nr\rt\t";
|
||||
|
||||
for (;;) {
|
||||
if (p[0] == '\0') return c;
|
||||
if (p[0] == c) return p[1];
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) { return c == '\"' || c == '\''; }
|
||||
|
||||
char *QuotedString::extractFrom(char *input, char **endPtr) {
|
||||
char firstChar = *input;
|
||||
|
||||
if (!isQuote(firstChar)) {
|
||||
// must start with a quote
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char stopChar = firstChar; // closing quote is the same as opening quote
|
||||
|
||||
char *startPtr = input + 1; // skip the quote
|
||||
char *readPtr = startPtr;
|
||||
char *writePtr = startPtr;
|
||||
char c;
|
||||
|
||||
for (;;) {
|
||||
c = *readPtr++;
|
||||
|
||||
if (c == '\0') {
|
||||
// premature ending
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (c == stopChar) {
|
||||
// closing quote
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\\') {
|
||||
// replace char
|
||||
c = unescapeChar(*readPtr++);
|
||||
}
|
||||
|
||||
*writePtr++ = c;
|
||||
}
|
||||
|
||||
// end the string here
|
||||
*writePtr = '\0';
|
||||
|
||||
// update end ptr
|
||||
*endPtr = readPtr;
|
||||
|
||||
return startPtr;
|
||||
}
|
17
src/Internals/StringBuilder.cpp
Normal file
17
src/Internals/StringBuilder.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../../include/ArduinoJson/Internals/StringBuilder.hpp"
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
size_t StringBuilder::write(uint8_t c) {
|
||||
if (length >= capacity) return 0;
|
||||
|
||||
buffer[length++] = c;
|
||||
buffer[length] = '\0';
|
||||
return 1;
|
||||
}
|
60
src/JsonArray.cpp
Normal file
60
src/JsonArray.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
|
||||
#include "../include/ArduinoJson/JsonBuffer.hpp"
|
||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonArray JsonArray::_invalid(NULL);
|
||||
|
||||
JsonVariant &JsonArray::at(int index) const {
|
||||
node_type *node = _firstNode;
|
||||
while (node && index--) node = node->next;
|
||||
return node ? node->content : JsonVariant::invalid();
|
||||
}
|
||||
|
||||
JsonVariant &JsonArray::add() {
|
||||
node_type *node = createNode();
|
||||
if (!node) return JsonVariant::invalid();
|
||||
|
||||
addNode(node);
|
||||
|
||||
return node->content;
|
||||
}
|
||||
|
||||
JsonArray &JsonArray::createNestedArray() {
|
||||
if (!_buffer) return JsonArray::invalid();
|
||||
JsonArray &array = _buffer->createArray();
|
||||
add(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
JsonObject &JsonArray::createNestedObject() {
|
||||
if (!_buffer) return JsonObject::invalid();
|
||||
JsonObject &object = _buffer->createObject();
|
||||
add(object);
|
||||
return object;
|
||||
}
|
||||
|
||||
void JsonArray::writeTo(JsonWriter &writer) const {
|
||||
writer.beginArray();
|
||||
|
||||
const node_type *child = _firstNode;
|
||||
while (child) {
|
||||
child->content.writeTo(writer);
|
||||
|
||||
child = child->next;
|
||||
if (!child) break;
|
||||
|
||||
writer.writeComma();
|
||||
}
|
||||
|
||||
writer.endArray();
|
||||
}
|
37
src/JsonBuffer.cpp
Normal file
37
src/JsonBuffer.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../include/ArduinoJson/JsonBuffer.hpp"
|
||||
|
||||
#include "../include/ArduinoJson/Internals/JsonParser.hpp"
|
||||
#include "../include/ArduinoJson/Internals/PlacementNew.hpp"
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonArray &JsonBuffer::createArray() {
|
||||
void *ptr = alloc(sizeof(JsonArray));
|
||||
if (ptr) return *new (ptr) JsonArray(this);
|
||||
return JsonArray::invalid();
|
||||
}
|
||||
|
||||
JsonObject &JsonBuffer::createObject() {
|
||||
void *ptr = alloc(sizeof(JsonObject));
|
||||
if (ptr) return *new (ptr) JsonObject(this);
|
||||
return JsonObject::invalid();
|
||||
}
|
||||
|
||||
JsonArray &JsonBuffer::parseArray(char *json, uint8_t nestingLimit) {
|
||||
JsonParser parser(this, json, nestingLimit);
|
||||
return parser.parseArray();
|
||||
}
|
||||
|
||||
JsonObject &JsonBuffer::parseObject(char *json, uint8_t nestingLimit) {
|
||||
JsonParser parser(this, json, nestingLimit);
|
||||
return parser.parseObject();
|
||||
}
|
86
src/JsonObject.cpp
Normal file
86
src/JsonObject.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
#include "../include/ArduinoJson/Internals/PlacementNew.hpp"
|
||||
#include "../include/ArduinoJson/Internals/StringBuilder.hpp"
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../include/ArduinoJson/JsonBuffer.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonObject JsonObject::_invalid(NULL);
|
||||
|
||||
JsonVariant &JsonObject::at(const char *key) {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value : JsonVariant::invalid();
|
||||
}
|
||||
|
||||
const JsonVariant &JsonObject::at(const char *key) const {
|
||||
node_type *node = getNodeAt(key);
|
||||
return node ? node->content.value : JsonVariant::invalid();
|
||||
}
|
||||
|
||||
JsonVariant &JsonObject::operator[](const char *key) {
|
||||
// try to find an existing node
|
||||
node_type *node = getNodeAt(key);
|
||||
|
||||
// not fount => create a new one
|
||||
if (!node) {
|
||||
node = createNode();
|
||||
if (!node) return JsonVariant::invalid();
|
||||
|
||||
node->content.key = key;
|
||||
addNode(node);
|
||||
}
|
||||
|
||||
return node->content.value;
|
||||
}
|
||||
|
||||
void JsonObject::remove(char const *key) { removeNode(getNodeAt(key)); }
|
||||
|
||||
JsonArray &JsonObject::createNestedArray(char const *key) {
|
||||
if (!_buffer) return JsonArray::invalid();
|
||||
JsonArray &array = _buffer->createArray();
|
||||
add(key, array);
|
||||
return array;
|
||||
}
|
||||
|
||||
JsonObject &JsonObject::createNestedObject(const char *key) {
|
||||
if (!_buffer) return JsonObject::invalid();
|
||||
JsonObject &object = _buffer->createObject();
|
||||
add(key, object);
|
||||
return object;
|
||||
}
|
||||
|
||||
JsonObject::node_type *JsonObject::getNodeAt(const char *key) const {
|
||||
for (node_type *node = _firstNode; node; node = node->next) {
|
||||
if (!strcmp(node->content.key, key)) return node;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void JsonObject::writeTo(JsonWriter &writer) const {
|
||||
writer.beginObject();
|
||||
|
||||
const node_type *node = _firstNode;
|
||||
while (node) {
|
||||
writer.writeString(node->content.key);
|
||||
writer.writeColon();
|
||||
node->content.value.writeTo(writer);
|
||||
|
||||
node = node->next;
|
||||
if (!node) break;
|
||||
|
||||
writer.writeComma();
|
||||
}
|
||||
|
||||
writer.endObject();
|
||||
}
|
108
src/JsonVariant.cpp
Normal file
108
src/JsonVariant.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "../include/ArduinoJson/JsonVariant.hpp"
|
||||
|
||||
#include "../include/ArduinoJson/JsonArray.hpp"
|
||||
#include "../include/ArduinoJson/JsonObject.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonVariant JsonVariant::_invalid(JSON_INVALID);
|
||||
|
||||
JsonVariant::operator JsonArray &() const {
|
||||
return _type == JSON_ARRAY ? *_content.asArray : JsonArray::invalid();
|
||||
}
|
||||
|
||||
JsonVariant::operator JsonObject &() const {
|
||||
return _type == JSON_OBJECT ? *_content.asObject : JsonObject::invalid();
|
||||
}
|
||||
|
||||
JsonVariant::operator bool() const {
|
||||
return _type == JSON_BOOLEAN ? _content.asBoolean : false;
|
||||
}
|
||||
|
||||
JsonVariant::operator const char *() const {
|
||||
return _type == JSON_STRING ? _content.asString : NULL;
|
||||
}
|
||||
|
||||
JsonVariant::operator double() const {
|
||||
return _type >= JSON_DOUBLE_0_DECIMALS ? _content.asDouble : 0;
|
||||
}
|
||||
|
||||
JsonVariant::operator long() const {
|
||||
return _type == JSON_LONG ? _content.asLong : 0;
|
||||
}
|
||||
|
||||
void JsonVariant::set(bool value) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = Internals::JSON_BOOLEAN;
|
||||
_content.asBoolean = value;
|
||||
}
|
||||
|
||||
void JsonVariant::set(const char *value) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_STRING;
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
void JsonVariant::set(double value, uint8_t decimals) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = static_cast<JsonVariantType>(JSON_DOUBLE_0_DECIMALS + decimals);
|
||||
_content.asDouble = value;
|
||||
}
|
||||
|
||||
void JsonVariant::set(long value) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_LONG;
|
||||
_content.asLong = value;
|
||||
}
|
||||
|
||||
void JsonVariant::set(JsonArray &array) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_ARRAY;
|
||||
_content.asArray = &array;
|
||||
}
|
||||
|
||||
void JsonVariant::set(JsonObject &object) {
|
||||
if (_type == JSON_INVALID) return;
|
||||
_type = JSON_OBJECT;
|
||||
_content.asObject = &object;
|
||||
}
|
||||
|
||||
size_t JsonVariant::size() const {
|
||||
if (_type == JSON_ARRAY) return _content.asArray->size();
|
||||
if (_type == JSON_OBJECT) return _content.asObject->size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
JsonVariant &JsonVariant::operator[](int index) {
|
||||
if (_type != JSON_ARRAY) return JsonVariant::invalid();
|
||||
return _content.asArray->operator[](index);
|
||||
}
|
||||
|
||||
JsonVariant &JsonVariant::operator[](const char *key) {
|
||||
if (_type != JSON_OBJECT) return JsonVariant::invalid();
|
||||
return _content.asObject->operator[](key);
|
||||
}
|
||||
|
||||
void JsonVariant::writeTo(JsonWriter &writer) const {
|
||||
if (is<const JsonArray &>())
|
||||
as<const JsonArray &>().writeTo(writer);
|
||||
else if (is<const JsonObject &>())
|
||||
as<const JsonObject &>().writeTo(writer);
|
||||
else if (is<const char *>())
|
||||
writer.writeString(as<const char *>());
|
||||
else if (is<long>())
|
||||
writer.writeLong(as<long>());
|
||||
else if (is<bool>())
|
||||
writer.writeBoolean(as<bool>());
|
||||
else if (is<double>()) {
|
||||
uint8_t decimals = static_cast<uint8_t>(_type - JSON_DOUBLE_0_DECIMALS);
|
||||
writer.writeDouble(as<double>(), decimals);
|
||||
}
|
||||
}
|
21
test/CMakeLists.txt
Normal file
21
test/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
set(GTEST_DIR ../third-party/gtest-1.7.0)
|
||||
|
||||
file(GLOB_RECURSE INC_FILES ../include/*.h)
|
||||
file(GLOB TESTS_FILES *.hpp *.cpp)
|
||||
|
||||
include_directories(
|
||||
../include
|
||||
${GTEST_DIR}
|
||||
${GTEST_DIR}/include)
|
||||
|
||||
add_definitions(-DGTEST_HAS_PTHREAD=0)
|
||||
|
||||
add_executable(ArduinoJsonTests
|
||||
${TESTS_FILES}
|
||||
${INC_FILES}
|
||||
${GTEST_DIR}/src/gtest-all.cc
|
||||
${GTEST_DIR}/src/gtest_main.cc)
|
||||
|
||||
target_link_libraries(ArduinoJsonTests ArduinoJson)
|
||||
|
||||
add_test(ArduinoJsonTests ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ArduinoJsonTests)
|
191
test/GbathreeBug.cpp
Normal file
191
test/GbathreeBug.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "Printers.hpp"
|
||||
|
||||
class GbathreeBug : public testing::Test {
|
||||
public:
|
||||
GbathreeBug() : object(buffer.parseObject(getJson())) {}
|
||||
|
||||
protected:
|
||||
char json[1024];
|
||||
StaticJsonBuffer<10000> buffer;
|
||||
const JsonObject& object;
|
||||
|
||||
private:
|
||||
char* getJson() {
|
||||
strcpy(json,
|
||||
"{\"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0,"
|
||||
"\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_"
|
||||
"baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":"
|
||||
"10000,\"actintensity1\":50,\"actintensity2\":255,\"measintensity\":"
|
||||
"255,\"calintensity\":255,\"pulses\":[50,50,50],\"act\":[2,1,2,2],"
|
||||
"\"red\":[2,2,2,2],\"detectors\":[[34,34,34,34],[34,34,34,34],[34,"
|
||||
"34,34,34],[34,34,34,34]],\"alta\":[2,2,2,2],\"altb\":[2,2,2,2],"
|
||||
"\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,"
|
||||
"15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],"
|
||||
"[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}");
|
||||
return json;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(GbathreeBug, Success) { EXPECT_TRUE(object.success()); }
|
||||
|
||||
TEST_F(GbathreeBug, ProtocolName) {
|
||||
EXPECT_STREQ("fluorescence", object.at("protocol_name").asString());
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Repeats) { EXPECT_EQ(1, object["repeats"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Wait) { EXPECT_EQ(0, object["wait"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Measurements) { EXPECT_EQ(3, object["measurements"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Meas2_Light) { EXPECT_EQ(15, object["meas2_light"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Meas1_Baseline) { EXPECT_EQ(0, object["meas1_baseline"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Act_Light) { EXPECT_EQ(20, object["act_light"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Pulsesize) { EXPECT_EQ(25, object["pulsesize"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Pulsedistance) {
|
||||
EXPECT_EQ(10000, object["pulsedistance"]);
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Actintensity1) { EXPECT_EQ(50, object["actintensity1"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Actintensity2) { EXPECT_EQ(255, object["actintensity2"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Measintensity) { EXPECT_EQ(255, object["measintensity"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Calintensity) { EXPECT_EQ(255, object["calintensity"]); }
|
||||
|
||||
TEST_F(GbathreeBug, Pulses) {
|
||||
// "pulses":[50,50,50]
|
||||
|
||||
JsonArray& array = object.at("pulses");
|
||||
EXPECT_TRUE(array.success());
|
||||
|
||||
EXPECT_EQ(3, array.size());
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
EXPECT_EQ(50, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Act) {
|
||||
// "act":[2,1,2,2]
|
||||
|
||||
JsonArray& array = object.at("act");
|
||||
EXPECT_TRUE(array.success());
|
||||
|
||||
EXPECT_EQ(4, array.size());
|
||||
EXPECT_EQ(2, array[0]);
|
||||
EXPECT_EQ(1, array[1]);
|
||||
EXPECT_EQ(2, array[2]);
|
||||
EXPECT_EQ(2, array[3]);
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Detectors) {
|
||||
// "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]]
|
||||
|
||||
JsonArray& array = object.at("detectors");
|
||||
EXPECT_TRUE(array.success());
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
JsonArray& nestedArray = array[i];
|
||||
EXPECT_EQ(4, nestedArray.size());
|
||||
|
||||
for (int j = 0; j < 4; j++) EXPECT_EQ(34, nestedArray[j]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Alta) {
|
||||
// alta:[2,2,2,2]
|
||||
|
||||
JsonArray& array = object.at("alta");
|
||||
EXPECT_TRUE(array.success());
|
||||
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EXPECT_EQ(2, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Altb) {
|
||||
// altb:[2,2,2,2]
|
||||
|
||||
JsonArray& array = object.at("altb");
|
||||
EXPECT_TRUE(array.success());
|
||||
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EXPECT_EQ(2, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Measlights) {
|
||||
// "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||
|
||||
JsonArray& array = object.at("measlights");
|
||||
EXPECT_TRUE(array.success());
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
JsonArray& nestedArray = array[i];
|
||||
|
||||
EXPECT_EQ(4, nestedArray.size());
|
||||
|
||||
for (int j = 0; j < 4; j++) EXPECT_EQ(15, nestedArray[j]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Measlights2) {
|
||||
// "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||
|
||||
JsonArray& array = object.at("measlights2");
|
||||
EXPECT_TRUE(array.success());
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
JsonArray& nestedArray = array[i];
|
||||
EXPECT_EQ(4, nestedArray.size());
|
||||
|
||||
for (int j = 0; j < 4; j++) EXPECT_EQ(15, nestedArray[j]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Altc) {
|
||||
// altc:[2,2,2,2]
|
||||
|
||||
JsonArray& array = object.at("altc");
|
||||
EXPECT_TRUE(array.success());
|
||||
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EXPECT_EQ(2, array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(GbathreeBug, Altd) {
|
||||
// altd:[2,2,2,2]
|
||||
|
||||
JsonArray& array = object.at("altd");
|
||||
EXPECT_TRUE(array.success());
|
||||
|
||||
EXPECT_EQ(4, array.size());
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EXPECT_EQ(2, array[i]);
|
||||
}
|
||||
}
|
104
test/IntegrationTests.cpp
Normal file
104
test/IntegrationTests.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class IntegrationTests : public testing::TestWithParam<const char*> {
|
||||
static const size_t MAX_JSON_SIZE = 10000;
|
||||
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
_input = GetParam();
|
||||
strcpy(inputBuffer, _input);
|
||||
}
|
||||
|
||||
void parseThenPrint(char* input, char* output) {
|
||||
StaticJsonBuffer<10000> json;
|
||||
json.parseObject(input).printTo(output, MAX_JSON_SIZE);
|
||||
}
|
||||
|
||||
void parseThenPrettyPrint(char* input, char* output) {
|
||||
StaticJsonBuffer<10000> json;
|
||||
json.parseObject(input).prettyPrintTo(output, MAX_JSON_SIZE);
|
||||
}
|
||||
|
||||
const char* _input;
|
||||
char inputBuffer[MAX_JSON_SIZE];
|
||||
char outputBuffer[MAX_JSON_SIZE];
|
||||
char intermediateBuffer[MAX_JSON_SIZE];
|
||||
};
|
||||
|
||||
TEST_P(IntegrationTests, ParseThenPrint) {
|
||||
parseThenPrint(inputBuffer, outputBuffer);
|
||||
ASSERT_STREQ(_input, outputBuffer);
|
||||
}
|
||||
|
||||
TEST_P(IntegrationTests, ParseThenPrettyPrintThenParseThenPrint) {
|
||||
parseThenPrettyPrint(inputBuffer, intermediateBuffer);
|
||||
parseThenPrint(intermediateBuffer, outputBuffer);
|
||||
ASSERT_STREQ(_input, outputBuffer);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
OpenWeatherMap, IntegrationTests,
|
||||
testing::Values(
|
||||
"{\"coord\":{\"lon\":145.77,\"lat\":-16.92},\"sys\":{\"type\":1,\"id\":"
|
||||
"8166,\"message\":0.1222,\"country\":\"AU\",\"sunrise\":1414784325,"
|
||||
"\"sunset\":1414830137},\"weather\":[{\"id\":801,\"main\":\"Clouds\","
|
||||
"\"description\":\"few clouds\",\"icon\":\"02n\"}],\"base\":\"cmc "
|
||||
"stations\",\"main\":{\"temp\":296.15,\"pressure\":1014,\"humidity\":"
|
||||
"83,\"temp_min\":296.15,\"temp_max\":296.15},\"wind\":{\"speed\":2.22,"
|
||||
"\"deg\":114.501},\"clouds\":{\"all\":20},\"dt\":1414846800,\"id\":"
|
||||
"2172797,\"name\":\"Cairns\",\"cod\":200}"));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
YahooQueryLanguage, IntegrationTests,
|
||||
testing::Values(
|
||||
"{\"query\":{\"count\":40,\"created\":\"2014-11-01T14:16:49Z\","
|
||||
"\"lang\":\"fr-FR\",\"results\":{\"item\":[{\"title\":\"Burkina army "
|
||||
"backs Zida as interim leader\"},{\"title\":\"British jets intercept "
|
||||
"Russian bombers\"},{\"title\":\"Doubts chip away at nation's most "
|
||||
"trusted agencies\"},{\"title\":\"Cruise ship stuck off Norway, no "
|
||||
"damage\"},{\"title\":\"U.S. military launches 10 air strikes in "
|
||||
"Syria, Iraq\"},{\"title\":\"Blackout hits Bangladesh as line from "
|
||||
"India fails\"},{\"title\":\"Burkina Faso president in Ivory Coast "
|
||||
"after ouster\"},{\"title\":\"Kurds in Turkey rally to back city "
|
||||
"besieged by IS\"},{\"title\":\"A majority of Scots would vote for "
|
||||
"independence now:poll\"},{\"title\":\"Tunisia elections possible "
|
||||
"model for region\"},{\"title\":\"Islamic State kills 85 more members "
|
||||
"of Iraqi tribe\"},{\"title\":\"Iraqi officials:IS extremists line "
|
||||
"up, kill 50\"},{\"title\":\"Burkina Faso army backs presidential "
|
||||
"guard official to lead transition\"},{\"title\":\"Kurdish peshmerga "
|
||||
"arrive with weapons in Syria's Kobani\"},{\"title\":\"Driver sought "
|
||||
"in crash that killed 3 on Halloween\"},{\"title\":\"Ex-Marine arrives "
|
||||
"in US after release from Mexico jail\"},{\"title\":\"UN panel "
|
||||
"scrambling to finish climate report\"},{\"title\":\"Investigators, "
|
||||
"Branson go to spacecraft crash site\"},{\"title\":\"Soldiers vie for "
|
||||
"power after Burkina Faso president quits\"},{\"title\":\"For a man "
|
||||
"without a party, turnout is big test\"},{\"title\":\"'We just had a "
|
||||
"hunch':US marshals nab Eric Frein\"},{\"title\":\"Boko Haram leader "
|
||||
"threatens to kill German hostage\"},{\"title\":\"Nurse free to move "
|
||||
"about as restrictions eased\"},{\"title\":\"Former Burkina president "
|
||||
"Compaore arrives in Ivory Coast:sources\"},{\"title\":\"Libyan port "
|
||||
"rebel leader refuses to hand over oil ports to rival "
|
||||
"group\"},{\"title\":\"Iraqi peshmerga fighters prepare for Syria "
|
||||
"battle\"},{\"title\":\"1 Dem Senate candidate welcoming Obama's "
|
||||
"help\"},{\"title\":\"Bikers cancel party after police recover "
|
||||
"bar\"},{\"title\":\"New question in Texas:Can Davis survive "
|
||||
"defeat?\"},{\"title\":\"Ukraine rebels to hold election, despite "
|
||||
"criticism\"},{\"title\":\"Iraqi officials say Islamic State group "
|
||||
"lines up, kills 50 tribesmen, women in Anbar "
|
||||
"province\"},{\"title\":\"James rebounds, leads Cavaliers past "
|
||||
"Bulls\"},{\"title\":\"UK warns travelers they could be terror "
|
||||
"targets\"},{\"title\":\"Hello Kitty celebrates 40th "
|
||||
"birthday\"},{\"title\":\"A look at people killed during space "
|
||||
"missions\"},{\"title\":\"Nigeria's purported Boko Haram leader says "
|
||||
"has 'married off' girls:AFP\"},{\"title\":\"Mexico orders immediate "
|
||||
"release of Marine veteran\"},{\"title\":\"As election closes in, "
|
||||
"Obama on center stage\"},{\"title\":\"Body of Zambian president "
|
||||
"arrives home\"},{\"title\":\"South Africa arrests 2 Vietnamese for "
|
||||
"poaching\"}]}}}"));
|
67
test/Issue10.cpp
Normal file
67
test/Issue10.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
struct Person {
|
||||
int id;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
class Issue10 : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
Person boss;
|
||||
boss.id = 1;
|
||||
strcpy(boss.name, "Jeff");
|
||||
Person employee;
|
||||
employee.id = 2;
|
||||
strcpy(employee.name, "John");
|
||||
persons[0] = boss;
|
||||
persons[1] = employee;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void checkJsonString(const T &p) {
|
||||
char buffer[256];
|
||||
p.printTo(buffer, sizeof(buffer));
|
||||
|
||||
EXPECT_STREQ("[{\"id\":1,\"name\":\"Jeff\"},{\"id\":2,\"name\":\"John\"}]",
|
||||
buffer);
|
||||
}
|
||||
|
||||
StaticJsonBuffer<JSON_ARRAY_SIZE(2) + 2 * JSON_OBJECT_SIZE(2)> json;
|
||||
Person persons[2];
|
||||
};
|
||||
|
||||
TEST_F(Issue10, PopulateArrayByAddingAnObject) {
|
||||
JsonArray &array = json.createArray();
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
JsonObject &object = json.createObject();
|
||||
|
||||
object["id"] = persons[i].id;
|
||||
object["name"] = persons[i].name;
|
||||
|
||||
array.add(object);
|
||||
}
|
||||
|
||||
checkJsonString(array);
|
||||
}
|
||||
|
||||
TEST_F(Issue10, PopulateArrayByCreatingNestedObjects) {
|
||||
JsonArray &array = json.createArray();
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
JsonObject &object = array.createNestedObject();
|
||||
|
||||
object["id"] = persons[i].id;
|
||||
object["name"] = persons[i].name;
|
||||
}
|
||||
|
||||
checkJsonString(array);
|
||||
}
|
136
test/JsonArray_Container_Tests.cpp
Normal file
136
test/JsonArray_Container_Tests.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_Container_Tests : public ::testing::Test {
|
||||
protected:
|
||||
JsonArray_Container_Tests() : array(json.createArray()) {}
|
||||
|
||||
template <typename T>
|
||||
void firstMustEqual(T expected) {
|
||||
itemMustEqual(0, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void secondMustEqual(T expected) {
|
||||
itemMustEqual(1, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void firstMustReference(const T& expected) {
|
||||
itemMustReference(0, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void secondMustReference(const T& expected) {
|
||||
itemMustReference(1, expected);
|
||||
}
|
||||
|
||||
void sizeMustBe(int expected) { EXPECT_EQ(expected, array.size()); }
|
||||
|
||||
StaticJsonBuffer<256> json;
|
||||
JsonArray& array;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void itemMustEqual(int index, T expected) {
|
||||
EXPECT_EQ(expected, array[index].as<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void itemMustReference(int index, const T& expected) {
|
||||
EXPECT_EQ(&expected, &array[index].as<T&>());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, SuccessIsTrue) {
|
||||
EXPECT_TRUE(array.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, InitialSizeIsZero) { sizeMustBe(0); }
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, Grow_WhenValuesAreAdded) {
|
||||
array.add("hello");
|
||||
sizeMustBe(1);
|
||||
|
||||
array.add("world");
|
||||
sizeMustBe(2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreIntegers) {
|
||||
array.add(123);
|
||||
array.add(456);
|
||||
|
||||
firstMustEqual(123);
|
||||
secondMustEqual(456);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreDoubles) {
|
||||
array.add(123.45);
|
||||
array.add(456.78);
|
||||
|
||||
firstMustEqual(123.45);
|
||||
secondMustEqual(456.78);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreBooleans) {
|
||||
array.add(true);
|
||||
array.add(false);
|
||||
|
||||
firstMustEqual(true);
|
||||
secondMustEqual(false);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreStrings) {
|
||||
const char* firstString = "h3110";
|
||||
const char* secondString = "w0r1d";
|
||||
|
||||
array.add(firstString);
|
||||
array.add(secondString);
|
||||
|
||||
firstMustEqual(firstString);
|
||||
secondMustEqual(secondString);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreNestedArrays) {
|
||||
JsonArray& innerarray1 = json.createArray();
|
||||
JsonArray& innerarray2 = json.createArray();
|
||||
|
||||
array.add(innerarray1);
|
||||
array.add(innerarray2);
|
||||
|
||||
firstMustReference(innerarray1);
|
||||
secondMustReference(innerarray2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanStoreNestedObjects) {
|
||||
JsonObject& innerObject1 = json.createObject();
|
||||
JsonObject& innerObject2 = json.createObject();
|
||||
|
||||
array.add(innerObject1);
|
||||
array.add(innerObject2);
|
||||
|
||||
firstMustReference(innerObject1);
|
||||
secondMustReference(innerObject2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanCreateNestedArrays) {
|
||||
JsonArray& innerarray1 = array.createNestedArray();
|
||||
JsonArray& innerarray2 = array.createNestedArray();
|
||||
|
||||
firstMustReference(innerarray1);
|
||||
secondMustReference(innerarray2);
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_Container_Tests, CanCreateNestedObjects) {
|
||||
JsonObject& innerObject1 = array.createNestedObject();
|
||||
JsonObject& innerObject2 = array.createNestedObject();
|
||||
|
||||
firstMustReference(innerObject1);
|
||||
secondMustReference(innerObject2);
|
||||
}
|
36
test/JsonArray_Invalid_Tests.cpp
Normal file
36
test/JsonArray_Invalid_Tests.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, AtFails) {
|
||||
ASSERT_FALSE(JsonArray::invalid().at(0).success());
|
||||
}
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, SubscriptFails) {
|
||||
ASSERT_FALSE(JsonArray::invalid()[0].success());
|
||||
}
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, AddFails) {
|
||||
JsonArray& array = JsonArray::invalid();
|
||||
array.add(1);
|
||||
ASSERT_EQ(0, array.size());
|
||||
}
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, CreateNestedArrayFails) {
|
||||
ASSERT_FALSE(JsonArray::invalid().createNestedArray().success());
|
||||
}
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, CreateNestedObjectFails) {
|
||||
ASSERT_FALSE(JsonArray::invalid().createNestedObject().success());
|
||||
}
|
||||
|
||||
TEST(JsonArray_Invalid_Tests, PrintToWritesBrackets) {
|
||||
char buffer[32];
|
||||
JsonArray::invalid().printTo(buffer, sizeof(buffer));
|
||||
ASSERT_STREQ("[]", buffer);
|
||||
}
|
27
test/JsonArray_Iterator_Tests.cpp
Normal file
27
test/JsonArray_Iterator_Tests.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(JsonArray_Iterator_Test, SimpleTest) {
|
||||
StaticJsonBuffer<100> jsonBuffer;
|
||||
|
||||
JsonArray &array = jsonBuffer.createArray();
|
||||
array.add(12);
|
||||
array.add(34);
|
||||
|
||||
JsonArray::iterator it = array.begin();
|
||||
JsonArray::iterator end = array.end();
|
||||
|
||||
EXPECT_NE(end, it);
|
||||
EXPECT_EQ(12, it->as<int>());
|
||||
++it;
|
||||
EXPECT_NE(end, it);
|
||||
EXPECT_EQ(34, it->as<int>());
|
||||
++it;
|
||||
EXPECT_EQ(end, it);
|
||||
}
|
79
test/JsonArray_PrettyPrintTo_Tests.cpp
Normal file
79
test/JsonArray_PrettyPrintTo_Tests.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_PrettyPrintTo_Tests : public testing::Test {
|
||||
public:
|
||||
JsonArray_PrettyPrintTo_Tests() : array(json.createArray()) {}
|
||||
|
||||
protected:
|
||||
StaticJsonBuffer<200> json;
|
||||
JsonArray& array;
|
||||
|
||||
void outputMustBe(const char* expected) {
|
||||
size_t n = array.prettyPrintTo(buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(expected, buffer);
|
||||
EXPECT_EQ(strlen(expected), n);
|
||||
}
|
||||
|
||||
private:
|
||||
char buffer[256];
|
||||
};
|
||||
|
||||
TEST_F(JsonArray_PrettyPrintTo_Tests, Empty) { outputMustBe("[]"); }
|
||||
|
||||
TEST_F(JsonArray_PrettyPrintTo_Tests, OneElement) {
|
||||
array.add(1);
|
||||
|
||||
outputMustBe(
|
||||
"[\r\n"
|
||||
" 1\r\n"
|
||||
"]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrettyPrintTo_Tests, TwoElements) {
|
||||
array.add(1);
|
||||
array.add(2);
|
||||
|
||||
outputMustBe(
|
||||
"[\r\n"
|
||||
" 1,\r\n"
|
||||
" 2\r\n"
|
||||
"]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrettyPrintTo_Tests, EmptyNestedArrays) {
|
||||
array.createNestedArray();
|
||||
array.createNestedArray();
|
||||
|
||||
outputMustBe(
|
||||
"[\r\n"
|
||||
" [],\r\n"
|
||||
" []\r\n"
|
||||
"]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrettyPrintTo_Tests, NestedArrays) {
|
||||
JsonArray& nested1 = array.createNestedArray();
|
||||
nested1.add(1);
|
||||
nested1.add(2);
|
||||
|
||||
JsonObject& nested2 = array.createNestedObject();
|
||||
nested2["key"] = 3;
|
||||
|
||||
outputMustBe(
|
||||
"[\r\n"
|
||||
" [\r\n"
|
||||
" 1,\r\n"
|
||||
" 2\r\n"
|
||||
" ],\r\n"
|
||||
" {\r\n"
|
||||
" \"key\": 3\r\n"
|
||||
" }\r\n"
|
||||
"]");
|
||||
}
|
125
test/JsonArray_PrintTo_Tests.cpp
Normal file
125
test/JsonArray_PrintTo_Tests.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonArray_PrintTo_Tests : public testing::Test {
|
||||
public:
|
||||
JsonArray_PrintTo_Tests() : array(json.createArray()) {}
|
||||
|
||||
protected:
|
||||
StaticJsonBuffer<JSON_ARRAY_SIZE(2)> json;
|
||||
JsonArray &array;
|
||||
|
||||
void outputMustBe(const char *expected) {
|
||||
size_t n = array.printTo(buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(expected, buffer);
|
||||
EXPECT_EQ(strlen(expected), n);
|
||||
}
|
||||
|
||||
private:
|
||||
char buffer[256];
|
||||
};
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, Empty) { outputMustBe("[]"); }
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, Null) {
|
||||
array.add(static_cast<char *>(0));
|
||||
|
||||
outputMustBe("[null]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneString) {
|
||||
array.add("hello");
|
||||
|
||||
outputMustBe("[\"hello\"]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, TwoStrings) {
|
||||
array.add("hello");
|
||||
array.add("world");
|
||||
|
||||
outputMustBe("[\"hello\",\"world\"]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneStringOverCapacity) {
|
||||
array.add("hello");
|
||||
array.add("world");
|
||||
array.add("lost");
|
||||
|
||||
outputMustBe("[\"hello\",\"world\"]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneDoubleDefaultDigits) {
|
||||
array.add(3.14159265358979323846);
|
||||
outputMustBe("[3.14]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneDoubleFourDigits) {
|
||||
array.add(3.14159265358979323846, 4);
|
||||
outputMustBe("[3.1416]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneInteger) {
|
||||
array.add(1);
|
||||
|
||||
outputMustBe("[1]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, TwoIntegers) {
|
||||
array.add(1);
|
||||
array.add(2);
|
||||
|
||||
outputMustBe("[1,2]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneIntegerOverCapacity) {
|
||||
array.add(1);
|
||||
array.add(2);
|
||||
array.add(3);
|
||||
|
||||
outputMustBe("[1,2]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneTrue) {
|
||||
array.add(true);
|
||||
|
||||
outputMustBe("[true]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneFalse) {
|
||||
array.add(false);
|
||||
|
||||
outputMustBe("[false]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, TwoBooleans) {
|
||||
array.add(false);
|
||||
array.add(true);
|
||||
|
||||
outputMustBe("[false,true]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneBooleanOverCapacity) {
|
||||
array.add(false);
|
||||
array.add(true);
|
||||
array.add(false);
|
||||
|
||||
outputMustBe("[false,true]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneEmptyNestedArray) {
|
||||
array.createNestedArray();
|
||||
|
||||
outputMustBe("[[]]");
|
||||
}
|
||||
|
||||
TEST_F(JsonArray_PrintTo_Tests, OneEmptyNestedHash) {
|
||||
array.createNestedObject();
|
||||
|
||||
outputMustBe("[{}]");
|
||||
}
|
126
test/JsonObject_Container_Tests.cpp
Normal file
126
test/JsonObject_Container_Tests.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonObject_Container_Tests : public ::testing::Test {
|
||||
public:
|
||||
JsonObject_Container_Tests() : object(json.createObject()) {}
|
||||
|
||||
protected:
|
||||
StaticJsonBuffer<256> json;
|
||||
JsonObject& object;
|
||||
};
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, InitialSizeIsZero) {
|
||||
EXPECT_EQ(0, object.size());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, Grow_WhenValuesAreAdded) {
|
||||
object["hello"];
|
||||
EXPECT_EQ(1, object.size());
|
||||
|
||||
object["world"];
|
||||
EXPECT_EQ(2, object.size());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, DoNotGrow_WhenSameValueIsAdded) {
|
||||
object["hello"];
|
||||
EXPECT_EQ(1, object.size());
|
||||
|
||||
object["hello"];
|
||||
EXPECT_EQ(1, object.size());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, Shrink_WhenValuesAreRemoved) {
|
||||
object["hello"];
|
||||
object["world"];
|
||||
|
||||
object.remove("hello");
|
||||
EXPECT_EQ(1, object.size());
|
||||
|
||||
object.remove("world");
|
||||
EXPECT_EQ(0, object.size());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests,
|
||||
DoNotShrink_WhenRemoveIsCalledWithAWrongKey) {
|
||||
object["hello"];
|
||||
object["world"];
|
||||
|
||||
object.remove(":-P");
|
||||
|
||||
EXPECT_EQ(2, object.size());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreIntegers) {
|
||||
object["hello"] = 123;
|
||||
object["world"] = 456;
|
||||
|
||||
EXPECT_EQ(123, object["hello"].as<int>());
|
||||
EXPECT_EQ(456, object["world"].as<int>());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreDoubles) {
|
||||
object["hello"] = 123.45;
|
||||
object["world"] = 456.78;
|
||||
|
||||
EXPECT_EQ(123.45, object["hello"].as<double>());
|
||||
EXPECT_EQ(456.78, object["world"].as<double>());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreBooleans) {
|
||||
object["hello"] = true;
|
||||
object["world"] = false;
|
||||
|
||||
EXPECT_TRUE(object["hello"].as<bool>());
|
||||
EXPECT_FALSE(object["world"].as<bool>());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreStrings) {
|
||||
object["hello"] = "h3110";
|
||||
object["world"] = "w0r1d";
|
||||
|
||||
EXPECT_STREQ("h3110", object["hello"].as<const char*>());
|
||||
EXPECT_STREQ("w0r1d", object["world"].as<const char*>());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreInnerArrays) {
|
||||
JsonArray& innerarray1 = json.createArray();
|
||||
JsonArray& innerarray2 = json.createArray();
|
||||
|
||||
object["hello"] = innerarray1;
|
||||
object["world"] = innerarray2;
|
||||
|
||||
EXPECT_EQ(&innerarray1, &object["hello"].asArray());
|
||||
EXPECT_EQ(&innerarray2, &object["world"].asArray());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreInnerObjects) {
|
||||
JsonObject& innerObject1 = json.createObject();
|
||||
JsonObject& innerObject2 = json.createObject();
|
||||
|
||||
object["hello"] = innerObject1;
|
||||
object["world"] = innerObject2;
|
||||
|
||||
EXPECT_EQ(&innerObject1, &object["hello"].asObject());
|
||||
EXPECT_EQ(&innerObject2, &object["world"].asObject());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnFalseForNonExistingKey) {
|
||||
EXPECT_FALSE(object.containsKey("hello"));
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnTrueForDefinedValue) {
|
||||
object.add("hello", 42);
|
||||
EXPECT_TRUE(object.containsKey("hello"));
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnFalseForUndefinedValue) {
|
||||
object.add("hello");
|
||||
EXPECT_FALSE(object.containsKey("hello"));
|
||||
}
|
36
test/JsonObject_Invalid_Tests.cpp
Normal file
36
test/JsonObject_Invalid_Tests.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, AtFails) {
|
||||
ASSERT_FALSE(JsonObject::invalid().at(0).success());
|
||||
}
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, SubscriptFails) {
|
||||
ASSERT_FALSE(JsonObject::invalid()[0].success());
|
||||
}
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, AddFails) {
|
||||
JsonObject& array = JsonObject::invalid();
|
||||
array.add("hello", "world");
|
||||
ASSERT_EQ(0, array.size());
|
||||
}
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, CreateNestedArrayFails) {
|
||||
ASSERT_FALSE(JsonObject::invalid().createNestedArray("hello").success());
|
||||
}
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, CreateNestedObjectFails) {
|
||||
ASSERT_FALSE(JsonObject::invalid().createNestedObject("world").success());
|
||||
}
|
||||
|
||||
TEST(JsonObject_Invalid_Tests, PrintToWritesBraces) {
|
||||
char buffer[32];
|
||||
JsonObject::invalid().printTo(buffer, sizeof(buffer));
|
||||
ASSERT_STREQ("{}", buffer);
|
||||
}
|
57
test/JsonObject_Iterator_Tests.cpp
Normal file
57
test/JsonObject_Iterator_Tests.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "Printers.hpp"
|
||||
|
||||
class JsonObject_Iterator_Test : public testing::Test {
|
||||
public:
|
||||
JsonObject_Iterator_Test() : object(_buffer.createObject()) {
|
||||
object["ab"] = 12;
|
||||
object["cd"] = 34;
|
||||
}
|
||||
|
||||
protected:
|
||||
StaticJsonBuffer<256> _buffer;
|
||||
JsonObject& object;
|
||||
};
|
||||
|
||||
TEST_F(JsonObject_Iterator_Test, NonConstIterator) {
|
||||
JsonObject::iterator it = object.begin();
|
||||
ASSERT_NE(object.end(), it);
|
||||
EXPECT_STREQ("ab", it->key);
|
||||
EXPECT_EQ(12, it->value);
|
||||
it->key = "a.b";
|
||||
it->value = 1.2;
|
||||
++it;
|
||||
ASSERT_NE(object.end(), it);
|
||||
EXPECT_STREQ("cd", it->key);
|
||||
EXPECT_EQ(34, it->value);
|
||||
it->key = "c.d";
|
||||
it->value = 3.4;
|
||||
++it;
|
||||
ASSERT_EQ(object.end(), it);
|
||||
|
||||
ASSERT_EQ(2, object.size());
|
||||
EXPECT_EQ(1.2, object["a.b"]);
|
||||
EXPECT_EQ(3.4, object["c.d"]);
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Iterator_Test, ConstIterator) {
|
||||
const JsonObject& const_object = object;
|
||||
JsonObject::const_iterator it = const_object.begin();
|
||||
|
||||
ASSERT_NE(const_object.end(), it);
|
||||
EXPECT_STREQ("ab", it->key);
|
||||
EXPECT_EQ(12, it->value);
|
||||
++it;
|
||||
ASSERT_NE(const_object.end(), it);
|
||||
EXPECT_STREQ("cd", it->key);
|
||||
EXPECT_EQ(34, it->value);
|
||||
++it;
|
||||
ASSERT_EQ(const_object.end(), it);
|
||||
}
|
77
test/JsonObject_PrettyPrintTo_Tests.cpp
Normal file
77
test/JsonObject_PrettyPrintTo_Tests.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonObject_PrettyPrintTo_Tests : public testing::Test {
|
||||
public:
|
||||
JsonObject_PrettyPrintTo_Tests() : object(json.createObject()) {}
|
||||
|
||||
protected:
|
||||
StaticJsonBuffer<300> json;
|
||||
JsonObject &object;
|
||||
|
||||
void outputMustBe(const char *expected) {
|
||||
size_t n = object.prettyPrintTo(buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(expected, buffer);
|
||||
EXPECT_EQ(strlen(expected), n);
|
||||
}
|
||||
|
||||
private:
|
||||
char buffer[256];
|
||||
};
|
||||
|
||||
TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyObject) { outputMustBe("{}"); }
|
||||
|
||||
TEST_F(JsonObject_PrettyPrintTo_Tests, OneMember) {
|
||||
object["key"] = "value";
|
||||
|
||||
outputMustBe(
|
||||
"{\r\n"
|
||||
" \"key\": \"value\"\r\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrettyPrintTo_Tests, TwoMembers) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
|
||||
outputMustBe(
|
||||
"{\r\n"
|
||||
" \"key1\": \"value1\",\r\n"
|
||||
" \"key2\": \"value2\"\r\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrettyPrintTo_Tests, EmptyNestedContainers) {
|
||||
object.createNestedObject("key1");
|
||||
object.createNestedArray("key2");
|
||||
|
||||
outputMustBe(
|
||||
"{\r\n"
|
||||
" \"key1\": {},\r\n"
|
||||
" \"key2\": []\r\n"
|
||||
"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrettyPrintTo_Tests, NestedContainers) {
|
||||
JsonObject &nested1 = object.createNestedObject("key1");
|
||||
nested1["a"] = 1;
|
||||
|
||||
JsonArray &nested2 = object.createNestedArray("key2");
|
||||
nested2.add(2);
|
||||
|
||||
outputMustBe(
|
||||
"{\r\n"
|
||||
" \"key1\": {\r\n"
|
||||
" \"a\": 1\r\n"
|
||||
" },\r\n"
|
||||
" \"key2\": [\r\n"
|
||||
" 2\r\n"
|
||||
" ]\r\n"
|
||||
"}");
|
||||
}
|
139
test/JsonObject_PrintTo_Tests.cpp
Normal file
139
test/JsonObject_PrintTo_Tests.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
class JsonObject_PrintTo_Tests : public testing::Test {
|
||||
public:
|
||||
JsonObject_PrintTo_Tests() : object(json.createObject()) {}
|
||||
|
||||
protected:
|
||||
void outputMustBe(const char *expected) {
|
||||
char actual[256];
|
||||
int result = object.printTo(actual, sizeof(actual));
|
||||
|
||||
EXPECT_STREQ(expected, actual);
|
||||
EXPECT_EQ(strlen(expected), result);
|
||||
}
|
||||
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(2)> json;
|
||||
JsonObject &object;
|
||||
};
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, EmptyObject) { outputMustBe("{}"); }
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneString) {
|
||||
object["key"] = "value";
|
||||
|
||||
outputMustBe("{\"key\":\"value\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, TwoStrings) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, RemoveFirst) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key1");
|
||||
|
||||
outputMustBe("{\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, RemoveLast) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key2");
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, RemoveUnexistingKey) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key3");
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, ReplaceExistingKey) {
|
||||
object["key"] = "value1";
|
||||
object["key"] = "value2";
|
||||
|
||||
outputMustBe("{\"key\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneStringOverCapacity) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object["key3"] = "value3";
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneInteger) {
|
||||
object["key"] = 1;
|
||||
outputMustBe("{\"key\":1}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneDoubleFourDigits) {
|
||||
object["key"].set(3.14159265358979323846, 4);
|
||||
outputMustBe("{\"key\":3.1416}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneDoubleDefaultDigits) {
|
||||
object["key"] = 3.14159265358979323846;
|
||||
outputMustBe("{\"key\":3.14}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneNull) {
|
||||
object["key"] = static_cast<char *>(0);
|
||||
outputMustBe("{\"key\":null}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneTrue) {
|
||||
object["key"] = true;
|
||||
outputMustBe("{\"key\":true}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneFalse) {
|
||||
object["key"] = false;
|
||||
outputMustBe("{\"key\":false}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedArrayViaProxy) {
|
||||
JsonArray &nestedArray = json.createArray();
|
||||
|
||||
object["key"] = nestedArray;
|
||||
|
||||
outputMustBe("{\"key\":[]}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedObjectViaProxy) {
|
||||
JsonObject &nestedArray = json.createObject();
|
||||
|
||||
object["key"] = nestedArray;
|
||||
|
||||
outputMustBe("{\"key\":{}}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedObject) {
|
||||
object.createNestedObject("key");
|
||||
|
||||
outputMustBe("{\"key\":{}}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedArray) {
|
||||
object.createNestedArray("key");
|
||||
|
||||
outputMustBe("{\"key\":[]}");
|
||||
}
|
164
test/JsonParser_Array_Tests.cpp
Normal file
164
test/JsonParser_Array_Tests.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonParser_Array_Tests : public testing::Test {
|
||||
protected:
|
||||
void whenInputIs(const char *json) {
|
||||
strcpy(_jsonString, json);
|
||||
_array = &_jsonBuffer.parseArray(_jsonString);
|
||||
}
|
||||
|
||||
void parseMustSucceed() { EXPECT_TRUE(_array->success()); }
|
||||
|
||||
void parseMustFail() {
|
||||
EXPECT_FALSE(_array->success());
|
||||
EXPECT_EQ(0, _array->size());
|
||||
}
|
||||
|
||||
void sizeMustBe(int expected) { ASSERT_EQ(expected, _array->size()); }
|
||||
|
||||
template <typename T>
|
||||
void firstElementMustBe(T expected) {
|
||||
elementAtIndexMustBe(0, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void secondElementMustBe(T expected) {
|
||||
elementAtIndexMustBe(1, expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void elementAtIndexMustBe(int index, T expected) {
|
||||
EXPECT_EQ(expected, _array->at(index).as<T>());
|
||||
}
|
||||
|
||||
void elementAtIndexMustBe(int index, const char *expected) {
|
||||
EXPECT_STREQ(expected, _array->at(index).as<const char *>());
|
||||
}
|
||||
|
||||
StaticJsonBuffer<256> _jsonBuffer;
|
||||
JsonArray *_array;
|
||||
char _jsonString[256];
|
||||
};
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, EmptyArray) {
|
||||
whenInputIs("[]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(0);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, MissingOpeningBracket) {
|
||||
whenInputIs("]");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, ArrayWithNoEnd) {
|
||||
whenInputIs("[");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, EmptyArrayWithLeadingSpaces) {
|
||||
whenInputIs(" []");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(0);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, Garbage) {
|
||||
whenInputIs("%*$£¤");
|
||||
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, OneInteger) {
|
||||
whenInputIs("[42]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
firstElementMustBe(42);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, OneIntegerWithSpacesBefore) {
|
||||
whenInputIs("[ \t\r\n42]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
firstElementMustBe(42);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, OneIntegerWithSpaceAfter) {
|
||||
whenInputIs("[42 \t\r\n]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
firstElementMustBe(42);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, TwoIntegers) {
|
||||
whenInputIs("[42,84]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
firstElementMustBe(42);
|
||||
secondElementMustBe(84);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, TwoDoubles) {
|
||||
whenInputIs("[4.2,1e2]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
firstElementMustBe(4.2);
|
||||
secondElementMustBe(1e2);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, TwoBooleans) {
|
||||
whenInputIs("[true,false]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
firstElementMustBe(true);
|
||||
secondElementMustBe(false);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, TwoNulls) {
|
||||
const char *const nullCharPtr = 0;
|
||||
|
||||
whenInputIs("[null,null]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
firstElementMustBe(nullCharPtr);
|
||||
secondElementMustBe(nullCharPtr);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, IncompleteNull) {
|
||||
whenInputIs("[nul!]");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, IncompleteTrue) {
|
||||
whenInputIs("[tru!]");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, IncompleteFalse) {
|
||||
whenInputIs("[fals!]");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Array_Tests, TwoStrings) {
|
||||
whenInputIs("[\"hello\",\"world\"]");
|
||||
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
firstElementMustBe("hello");
|
||||
secondElementMustBe("world");
|
||||
}
|
54
test/JsonParser_Nested_Tests.cpp
Normal file
54
test/JsonParser_Nested_Tests.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(JsonParser_Nested_Tests, ArrayNestedInObject) {
|
||||
StaticJsonBuffer<256> jsonBuffer;
|
||||
char jsonString[] = " { \"ab\" : [ 1 , 2 ] , \"cd\" : [ 3 , 4 ] } ";
|
||||
|
||||
JsonObject &object = jsonBuffer.parseObject(jsonString);
|
||||
JsonArray &array1 = object["ab"];
|
||||
JsonArray &array2 = object["cd"];
|
||||
|
||||
ASSERT_TRUE(object.success());
|
||||
|
||||
ASSERT_TRUE(array1.success());
|
||||
ASSERT_TRUE(array2.success());
|
||||
|
||||
ASSERT_EQ(2, array1.size());
|
||||
ASSERT_EQ(2, array2.size());
|
||||
|
||||
EXPECT_EQ(1, array1[0].as<int>());
|
||||
EXPECT_EQ(2, array1[1].as<int>());
|
||||
|
||||
EXPECT_EQ(3, array2[0].as<int>());
|
||||
EXPECT_EQ(4, array2[1].as<int>());
|
||||
}
|
||||
|
||||
TEST(JsonParser_Nested_Tests, ObjectNestedInArray) {
|
||||
StaticJsonBuffer<256> jsonBuffer;
|
||||
char jsonString[] =
|
||||
" [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] ";
|
||||
|
||||
JsonArray &array = jsonBuffer.parseArray(jsonString);
|
||||
JsonObject &object1 = array[0];
|
||||
JsonObject &object2 = array[1];
|
||||
|
||||
ASSERT_TRUE(array.success());
|
||||
|
||||
ASSERT_TRUE(object1.success());
|
||||
ASSERT_TRUE(object2.success());
|
||||
|
||||
ASSERT_EQ(2, object1.size());
|
||||
ASSERT_EQ(2, object2.size());
|
||||
|
||||
EXPECT_EQ(1, object1["a"].as<int>());
|
||||
EXPECT_EQ(2, object1["b"].as<int>());
|
||||
EXPECT_EQ(3, object2["c"].as<int>());
|
||||
EXPECT_EQ(4, object2["d"].as<int>());
|
||||
}
|
84
test/JsonParser_NestingLimit_Tests.cpp
Normal file
84
test/JsonParser_NestingLimit_Tests.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonParser_NestingLimit_Tests : public testing::Test {
|
||||
protected:
|
||||
void whenNestingLimitIs(uint8_t nestingLimit) {
|
||||
_nestingLimit = nestingLimit;
|
||||
}
|
||||
|
||||
void parseArrayMustFail(const char *json) {
|
||||
ASSERT_FALSE(tryParseArray(json));
|
||||
}
|
||||
|
||||
void parseArrayMustSucceed(const char *json) {
|
||||
ASSERT_TRUE(tryParseArray(json));
|
||||
}
|
||||
|
||||
void parseObjectMustFail(const char *json) {
|
||||
ASSERT_FALSE(tryParseObject(json));
|
||||
}
|
||||
|
||||
void parseObjectMustSucceed(const char *json) {
|
||||
ASSERT_TRUE(tryParseObject(json));
|
||||
}
|
||||
|
||||
private:
|
||||
bool tryParseArray(const char *json) {
|
||||
StaticJsonBuffer<256> buffer;
|
||||
char s[256];
|
||||
strcpy(s, json);
|
||||
return buffer.parseArray(s, _nestingLimit).success();
|
||||
}
|
||||
|
||||
bool tryParseObject(const char *json) {
|
||||
StaticJsonBuffer<256> buffer;
|
||||
char s[256];
|
||||
strcpy(s, json);
|
||||
return buffer.parseObject(s, _nestingLimit).success();
|
||||
}
|
||||
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
TEST_F(JsonParser_NestingLimit_Tests, ParseArrayWithNestingLimit0) {
|
||||
whenNestingLimitIs(0);
|
||||
parseArrayMustSucceed("[]");
|
||||
parseArrayMustFail("[[]]");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_NestingLimit_Tests, ParseArrayWithNestingLimit1) {
|
||||
whenNestingLimitIs(1);
|
||||
parseArrayMustSucceed("[[]]");
|
||||
parseArrayMustFail("[[[]]]");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_NestingLimit_Tests, ParseArrayWithNestingLimit2) {
|
||||
whenNestingLimitIs(2);
|
||||
parseArrayMustSucceed("[[[]]]");
|
||||
parseArrayMustFail("[[[[]]]]");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_NestingLimit_Tests, ParseObjectWithNestingLimit0) {
|
||||
whenNestingLimitIs(0);
|
||||
parseObjectMustSucceed("{}");
|
||||
parseObjectMustFail("{\"key\":{}}");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_NestingLimit_Tests, ParseObjectWithNestingLimit1) {
|
||||
whenNestingLimitIs(1);
|
||||
parseObjectMustSucceed("{\"key\":{}}");
|
||||
parseObjectMustFail("{\"key\":{\"key\":{}}}");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_NestingLimit_Tests, ParseObjectWithNestingLimit2) {
|
||||
whenNestingLimitIs(2);
|
||||
parseObjectMustSucceed("{\"key\":{\"key\":{}}}");
|
||||
parseObjectMustFail("{\"key\":{\"key\":{\"key\":{}}}}");
|
||||
}
|
173
test/JsonParser_Object_Tests.cpp
Normal file
173
test/JsonParser_Object_Tests.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonParser_Object_Test : public testing::Test {
|
||||
protected:
|
||||
void whenInputIs(const char *jsonString) {
|
||||
strcpy(_jsonString, jsonString);
|
||||
_object = &_jsonBuffer.parseObject(_jsonString);
|
||||
}
|
||||
|
||||
void parseMustSucceed() { EXPECT_TRUE(_object->success()); }
|
||||
|
||||
void parseMustFail() { EXPECT_FALSE(_object->success()); }
|
||||
|
||||
void sizeMustBe(int expected) { EXPECT_EQ(expected, _object->size()); }
|
||||
|
||||
void keyMustHaveValue(const char *key, const char *expected) {
|
||||
EXPECT_STREQ(expected, _object->at(key).as<const char *>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void keyMustHaveValue(const char *key, T expected) {
|
||||
EXPECT_EQ(expected, _object->at(key).as<T>());
|
||||
}
|
||||
|
||||
private:
|
||||
StaticJsonBuffer<256> _jsonBuffer;
|
||||
JsonObject *_object;
|
||||
char _jsonString[256];
|
||||
};
|
||||
|
||||
TEST_F(JsonParser_Object_Test, EmptyObject) {
|
||||
whenInputIs("{}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(0);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, MissingOpeningBrace) {
|
||||
whenInputIs("}");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, MissingClosingBrace) {
|
||||
whenInputIs("{");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, MissingColonAndValue) {
|
||||
whenInputIs("{\"key\"}");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, MissingQuotesAndColonAndValue) {
|
||||
whenInputIs("{key}");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, OneString) {
|
||||
whenInputIs("{\"key\":\"value\"}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
keyMustHaveValue("key", "value");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, OneStringSingleQuotes) {
|
||||
whenInputIs("{'key':'value'}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
keyMustHaveValue("key", "value");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, OneStringSpaceBeforeKey) {
|
||||
whenInputIs("{ \"key\":\"value\"}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
keyMustHaveValue("key", "value");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, OneStringSpaceAfterKey) {
|
||||
whenInputIs("{\"key\" :\"value\"}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
keyMustHaveValue("key", "value");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, OneStringSpaceBeforeValue) {
|
||||
whenInputIs("{\"key\": \"value\"}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
keyMustHaveValue("key", "value");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, OneStringSpaceAfterValue) {
|
||||
whenInputIs("{\"key\":\"value\" }");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(1);
|
||||
keyMustHaveValue("key", "value");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, TwoStrings) {
|
||||
whenInputIs("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
keyMustHaveValue("key1", "value1");
|
||||
keyMustHaveValue("key2", "value2");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, TwoStringsSpaceBeforeComma) {
|
||||
whenInputIs("{\"key1\":\"value1\" ,\"key2\":\"value2\"}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
keyMustHaveValue("key1", "value1");
|
||||
keyMustHaveValue("key2", "value2");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, TwoStringsSpaceAfterComma) {
|
||||
whenInputIs("{\"key1\":\"value1\" ,\"key2\":\"value2\"}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
keyMustHaveValue("key1", "value1");
|
||||
keyMustHaveValue("key2", "value2");
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, EndingWithAComma) {
|
||||
whenInputIs("{\"key1\":\"value1\",}");
|
||||
parseMustFail();
|
||||
sizeMustBe(0);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, TwoIntergers) {
|
||||
whenInputIs("{\"key1\":42,\"key2\":-42}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
keyMustHaveValue("key1", 42);
|
||||
keyMustHaveValue("key2", -42);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, TwoDoubles) {
|
||||
whenInputIs("{\"key1\":12.345,\"key2\":-7E89}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
keyMustHaveValue("key1", 12.345);
|
||||
keyMustHaveValue("key2", -7E89);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, TwoBooleans) {
|
||||
whenInputIs("{\"key1\":true,\"key2\":false}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
keyMustHaveValue("key1", true);
|
||||
keyMustHaveValue("key2", false);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, TwoNulls) {
|
||||
const char *const nullstr = 0;
|
||||
|
||||
whenInputIs("{\"key1\":null,\"key2\":null}");
|
||||
parseMustSucceed();
|
||||
sizeMustBe(2);
|
||||
keyMustHaveValue("key1", nullstr);
|
||||
keyMustHaveValue("key2", nullstr);
|
||||
}
|
||||
|
||||
TEST_F(JsonParser_Object_Test, NullForKey) {
|
||||
whenInputIs("null:\"value\"}");
|
||||
parseMustFail();
|
||||
}
|
96
test/JsonVariant_Comparison_Tests.cpp
Normal file
96
test/JsonVariant_Comparison_Tests.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson/JsonVariant.hpp>
|
||||
#include "Printers.hpp"
|
||||
|
||||
using namespace ArduinoJson;
|
||||
|
||||
class JsonVariant_Comparison_Tests : public ::testing::Test {
|
||||
protected:
|
||||
template <typename T>
|
||||
void testValue(T low, T mid, T high) {
|
||||
setValueTo(mid);
|
||||
mustBeEqualTo(mid);
|
||||
mustBeGreaterThan(low);
|
||||
mustBeLessThan(high);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void setValueTo(T expected) {
|
||||
actual = expected;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void mustBeEqualTo(T expected) {
|
||||
EXPECT_EQ(expected, actual); // operator==
|
||||
EXPECT_EQ(actual, expected); // operator==
|
||||
EXPECT_LE(expected, actual); // operator<=
|
||||
EXPECT_LE(actual, expected); // operator<=
|
||||
EXPECT_GE(expected, actual); // operator>=
|
||||
EXPECT_GE(actual, expected); // operator>=
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void mustBeGreaterThan(T expected) {
|
||||
EXPECT_GT(actual, expected); // operator>
|
||||
EXPECT_LT(expected, actual); // operator<
|
||||
EXPECT_NE(actual, expected); // operator!=
|
||||
EXPECT_NE(expected, actual); // operator!=
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void mustBeLessThan(T expected) {
|
||||
EXPECT_LT(actual, expected); // operator<
|
||||
EXPECT_GT(expected, actual); // operator<
|
||||
EXPECT_NE(actual, expected); // operator!=
|
||||
EXPECT_NE(expected, actual); // operator!=
|
||||
}
|
||||
|
||||
JsonVariant actual;
|
||||
};
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, Double) {
|
||||
testValue<double>(123.44, 123.45, 123.46);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, Float) {
|
||||
testValue<float>(123.44f, 123.45f, 123.46f);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, SChar) {
|
||||
testValue<signed char>(122, 123, 124);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, SInt) {
|
||||
testValue<signed int>(122, 123, 124);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, SLong) {
|
||||
testValue<signed long>(122L, 123L, 124L);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, SShort) {
|
||||
testValue<signed short>(122, 123, 124);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, UChar) {
|
||||
testValue<unsigned char>(122, 123, 124);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, UInt) {
|
||||
testValue<unsigned int>(122, 123, 124);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, ULong) {
|
||||
testValue<unsigned long>(122L, 123L, 124L);
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Comparison_Tests, UShort) {
|
||||
testValue<unsigned short>(122, 123, 124);
|
||||
}
|
67
test/JsonVariant_Copy_Tests.cpp
Normal file
67
test/JsonVariant_Copy_Tests.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonVariant_Copy_Tests : public ::testing::Test {
|
||||
protected:
|
||||
StaticJsonBuffer<200> json;
|
||||
JsonVariant variant1;
|
||||
JsonVariant variant2;
|
||||
};
|
||||
|
||||
TEST_F(JsonVariant_Copy_Tests, IntegersAreCopiedByValue) {
|
||||
variant1 = 123;
|
||||
variant2 = variant1;
|
||||
variant1 = 456;
|
||||
|
||||
EXPECT_EQ(123, variant2.as<int>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Copy_Tests, DoublesAreCopiedByValue) {
|
||||
variant1 = 123.45;
|
||||
variant2 = variant1;
|
||||
variant1 = 456.78;
|
||||
|
||||
EXPECT_EQ(123.45, variant2.as<double>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Copy_Tests, BooleansAreCopiedByValue) {
|
||||
variant1 = true;
|
||||
variant2 = variant1;
|
||||
variant1 = false;
|
||||
|
||||
EXPECT_TRUE(variant2.as<bool>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Copy_Tests, StringsAreCopiedByValue) {
|
||||
variant1 = "hello";
|
||||
variant2 = variant1;
|
||||
variant1 = "world";
|
||||
|
||||
EXPECT_STREQ("hello", variant2.as<const char *>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Copy_Tests, ObjectsAreCopiedByReference) {
|
||||
JsonObject &object = json.createObject();
|
||||
|
||||
variant1 = object;
|
||||
|
||||
object["hello"] = "world";
|
||||
|
||||
EXPECT_EQ(1, variant1.asObject().size());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Copy_Tests, ArraysAreCopiedByReference) {
|
||||
JsonArray &array = json.createArray();
|
||||
|
||||
variant1 = array;
|
||||
|
||||
array.add("world");
|
||||
|
||||
EXPECT_EQ(1, variant1.asArray().size());
|
||||
}
|
75
test/JsonVariant_Invalid_Tests.cpp
Normal file
75
test/JsonVariant_Invalid_Tests.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "Printers.hpp"
|
||||
|
||||
class JsonVariant_Invalid_Tests : public ::testing::Test {
|
||||
public:
|
||||
JsonVariant_Invalid_Tests() : variant(JsonVariant::invalid()) {}
|
||||
|
||||
protected:
|
||||
JsonVariant variant;
|
||||
};
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, SuccessReturnsFalse) {
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, AsLongReturns0) {
|
||||
EXPECT_EQ(0, variant.as<long>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, AsStringReturnsNull) {
|
||||
EXPECT_EQ(0, variant.asString());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, AsDoubleReturns0) {
|
||||
EXPECT_EQ(0, variant.as<double>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, AsBoolReturnsFalse) {
|
||||
EXPECT_FALSE(variant.as<bool>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, AsArrayReturnInvalid) {
|
||||
EXPECT_EQ(JsonArray::invalid(), variant.asArray());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, AsObjectReturnInvalid) {
|
||||
EXPECT_EQ(JsonObject::invalid(), variant.asObject());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToLong) {
|
||||
variant = 0L;
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToDouble) {
|
||||
variant = 0.0;
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToString) {
|
||||
variant = static_cast<const char*>(NULL);
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToBool) {
|
||||
variant = false;
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToArray) {
|
||||
variant = JsonArray::invalid();
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Invalid_Tests, CanNotBeSetToObject) {
|
||||
variant = JsonObject::invalid();
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
72
test/JsonVariant_PrintTo_Tests.cpp
Normal file
72
test/JsonVariant_PrintTo_Tests.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonVariant_PrintTo_Tests : public testing::Test {
|
||||
protected:
|
||||
JsonVariant variant;
|
||||
|
||||
void outputMustBe(const char *expected) {
|
||||
char buffer[256] = "";
|
||||
size_t n = variant.printTo(buffer, sizeof(buffer));
|
||||
EXPECT_STREQ(expected, buffer);
|
||||
EXPECT_EQ(strlen(expected), n);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, Empty) { outputMustBe(""); }
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, Null) {
|
||||
variant = static_cast<char *>(0);
|
||||
outputMustBe("null");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, String) {
|
||||
variant = "hello";
|
||||
outputMustBe("\"hello\"");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, DoubleZero) {
|
||||
variant = 0.0;
|
||||
outputMustBe("0.00");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, DoubleDefaultDigits) {
|
||||
variant = 3.14159265358979323846;
|
||||
outputMustBe("3.14");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, DoubleFourDigits) {
|
||||
variant.set(3.14159265358979323846, 4);
|
||||
outputMustBe("3.1416");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, Integer) {
|
||||
variant = 42;
|
||||
outputMustBe("42");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, Long) {
|
||||
variant = 42L;
|
||||
outputMustBe("42");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, Char) {
|
||||
variant = '*';
|
||||
outputMustBe("42");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, True) {
|
||||
variant = true;
|
||||
outputMustBe("true");
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_PrintTo_Tests, OneFalse) {
|
||||
variant = false;
|
||||
outputMustBe("false");
|
||||
}
|
48
test/JsonVariant_Storage_Tests.cpp
Normal file
48
test/JsonVariant_Storage_Tests.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonVariant_Storage_Tests : public ::testing::Test {
|
||||
protected:
|
||||
template <typename T>
|
||||
void testValue(T expected) {
|
||||
actual.set(expected);
|
||||
EXPECT_EQ(expected, actual.as<T>());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void testReference(T &expected) {
|
||||
actual.set(expected);
|
||||
EXPECT_EQ(expected, actual.as<T &>());
|
||||
}
|
||||
|
||||
private:
|
||||
JsonVariant actual;
|
||||
};
|
||||
|
||||
TEST_F(JsonVariant_Storage_Tests, Double) { testValue<double>(123.45); }
|
||||
TEST_F(JsonVariant_Storage_Tests, False) { testValue<bool>(false); }
|
||||
TEST_F(JsonVariant_Storage_Tests, Float) { testValue<float>(123.45f); }
|
||||
TEST_F(JsonVariant_Storage_Tests, Null) { testValue<const char *>(NULL); }
|
||||
TEST_F(JsonVariant_Storage_Tests, SChar) { testValue<signed char>(123); }
|
||||
TEST_F(JsonVariant_Storage_Tests, SInt) { testValue<signed int>(123); }
|
||||
TEST_F(JsonVariant_Storage_Tests, SLong) { testValue<signed long>(123L); }
|
||||
TEST_F(JsonVariant_Storage_Tests, SShort) { testValue<signed short>(123); }
|
||||
TEST_F(JsonVariant_Storage_Tests, String) { testValue<const char *>("hello"); }
|
||||
TEST_F(JsonVariant_Storage_Tests, True) { testValue<bool>(true); }
|
||||
TEST_F(JsonVariant_Storage_Tests, UChar) { testValue<unsigned char>(123); }
|
||||
TEST_F(JsonVariant_Storage_Tests, UInt) { testValue<unsigned int>(123U); }
|
||||
TEST_F(JsonVariant_Storage_Tests, ULong) { testValue<unsigned long>(123UL); }
|
||||
TEST_F(JsonVariant_Storage_Tests, UShort) { testValue<unsigned short>(123); }
|
||||
|
||||
TEST_F(JsonVariant_Storage_Tests, CanStoreObject) {
|
||||
StaticJsonBuffer<200> json;
|
||||
JsonObject &object = json.createObject();
|
||||
|
||||
testReference(object);
|
||||
}
|
64
test/JsonVariant_Subscript_Tests.cpp
Normal file
64
test/JsonVariant_Subscript_Tests.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class JsonVariant_Subscript_Tests : public ::testing::Test {
|
||||
protected:
|
||||
StaticJsonBuffer<200> buffer;
|
||||
JsonVariant variant;
|
||||
};
|
||||
|
||||
TEST_F(JsonVariant_Subscript_Tests, Array) {
|
||||
JsonArray &array = buffer.createArray();
|
||||
array.add("element at index 0");
|
||||
array.add("element at index 1");
|
||||
|
||||
variant = array;
|
||||
|
||||
EXPECT_EQ(2, variant.size());
|
||||
EXPECT_STREQ("element at index 0", variant[0].asString());
|
||||
EXPECT_STREQ("element at index 1", variant[1].asString());
|
||||
EXPECT_FALSE(variant[-1].success());
|
||||
EXPECT_FALSE(variant[3].success());
|
||||
EXPECT_FALSE(variant["0"].success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Subscript_Tests, Object) {
|
||||
JsonObject &object = buffer.createObject();
|
||||
object["a"] = "element at key \"a\"";
|
||||
object["b"] = "element at key \"b\"";
|
||||
|
||||
variant = object;
|
||||
|
||||
EXPECT_EQ(2, variant.size());
|
||||
EXPECT_STREQ("element at key \"a\"", variant["a"].asString());
|
||||
EXPECT_STREQ("element at key \"b\"", variant["b"].asString());
|
||||
EXPECT_FALSE(variant["c"].success());
|
||||
EXPECT_FALSE(variant[0].success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Subscript_Tests, Undefined) {
|
||||
variant = JsonVariant();
|
||||
EXPECT_EQ(0, variant.size());
|
||||
EXPECT_FALSE(variant["0"].success());
|
||||
EXPECT_FALSE(variant[0].success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Subscript_Tests, Invalid) {
|
||||
variant = JsonVariant::invalid();
|
||||
EXPECT_EQ(0, variant.size());
|
||||
EXPECT_FALSE(variant["0"].success());
|
||||
EXPECT_FALSE(variant[0].success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Subscript_Tests, String) {
|
||||
variant = "hello world";
|
||||
EXPECT_EQ(0, variant.size());
|
||||
EXPECT_FALSE(variant["0"].success());
|
||||
EXPECT_FALSE(variant[0].success());
|
||||
}
|
72
test/JsonVariant_Undefined_Tests.cpp
Normal file
72
test/JsonVariant_Undefined_Tests.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include "Printers.hpp"
|
||||
|
||||
class JsonVariant_Undefined_Tests : public ::testing::Test {
|
||||
protected:
|
||||
JsonVariant variant;
|
||||
};
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, SuccessReturnsFalse) {
|
||||
EXPECT_FALSE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, AsLongReturns0) {
|
||||
EXPECT_EQ(0, variant.as<long>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, AsStringReturnsNull) {
|
||||
EXPECT_EQ(0, variant.asString());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, AsDoubleReturns0) {
|
||||
EXPECT_EQ(0, variant.as<double>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, AsBoolReturnsFalse) {
|
||||
EXPECT_FALSE(variant.as<bool>());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, AsArrayReturnInvalid) {
|
||||
EXPECT_EQ(JsonArray::invalid(), variant.asArray());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, AsObjectReturnInvalid) {
|
||||
EXPECT_EQ(JsonObject::invalid(), variant.asObject());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToLong) {
|
||||
variant = 0L;
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToDouble) {
|
||||
variant = 0.0;
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToString) {
|
||||
variant = static_cast<const char*>(NULL);
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToBool) {
|
||||
variant = false;
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToArray) {
|
||||
variant = JsonArray::invalid();
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
||||
|
||||
TEST_F(JsonVariant_Undefined_Tests, CanBeSetToObject) {
|
||||
variant = JsonObject::invalid();
|
||||
EXPECT_TRUE(variant.success());
|
||||
}
|
38
test/Printers.cpp
Normal file
38
test/Printers.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include "Printers.hpp"
|
||||
#include <ArduinoJson/JsonArray.hpp>
|
||||
|
||||
class StreamPrintAdapter : public Print {
|
||||
public:
|
||||
explicit StreamPrintAdapter(std::ostream& os) : _os(os) {}
|
||||
|
||||
virtual size_t write(uint8_t c) {
|
||||
_os << static_cast<char>(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
// cannot be assigned
|
||||
StreamPrintAdapter& operator=(const StreamPrintAdapter&);
|
||||
|
||||
std::ostream& _os;
|
||||
};
|
||||
|
||||
std::ostream& ArduinoJson::operator<<(std::ostream& os,
|
||||
const ArduinoJson::JsonVariant& v) {
|
||||
StreamPrintAdapter adapter(os);
|
||||
v.printTo(adapter);
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream& ArduinoJson::operator<<(std::ostream& os,
|
||||
const ArduinoJson::JsonArray& v) {
|
||||
StreamPrintAdapter adapter(os);
|
||||
v.printTo(adapter);
|
||||
return os;
|
||||
}
|
15
test/Printers.hpp
Normal file
15
test/Printers.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/JsonVariant.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace ArduinoJson {
|
||||
std::ostream& operator<<(std::ostream& os, const ArduinoJson::JsonVariant& v);
|
||||
std::ostream& operator<<(std::ostream& os, const ArduinoJson::JsonArray& v);
|
||||
}
|
130
test/QuotedString_ExtractFrom_Tests.cpp
Normal file
130
test/QuotedString_ExtractFrom_Tests.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson/Internals/QuotedString.hpp>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
class QuotedString_ExtractFrom_Tests : public testing::Test {
|
||||
protected:
|
||||
void whenInputIs(const char *json) {
|
||||
strcpy(_jsonString, json);
|
||||
_result = QuotedString::extractFrom(_jsonString, &_trailing);
|
||||
}
|
||||
|
||||
void resultMustBe(const char *expected) { EXPECT_STREQ(expected, _result); }
|
||||
|
||||
void trailingMustBe(const char *expected) {
|
||||
EXPECT_STREQ(expected, _trailing);
|
||||
}
|
||||
|
||||
private:
|
||||
char _jsonString[256];
|
||||
char *_result;
|
||||
char *_trailing;
|
||||
};
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EmptyDoubleQuotedString) {
|
||||
whenInputIs("\"\"");
|
||||
|
||||
resultMustBe("");
|
||||
trailingMustBe("");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, NoQuotes) {
|
||||
whenInputIs("hello world");
|
||||
|
||||
resultMustBe(0);
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EmptySingleQuotedString) {
|
||||
whenInputIs("''");
|
||||
|
||||
resultMustBe("");
|
||||
trailingMustBe("");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, SimpleDoubleQuotedString) {
|
||||
whenInputIs("\"hello world\"");
|
||||
|
||||
resultMustBe("hello world");
|
||||
trailingMustBe("");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, DoubleQuotedStringWithTrailing) {
|
||||
whenInputIs("\"hello\" world");
|
||||
|
||||
resultMustBe("hello");
|
||||
trailingMustBe(" world");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, SingleQuotedStringWithTrailing) {
|
||||
whenInputIs("'hello' world");
|
||||
|
||||
resultMustBe("hello");
|
||||
trailingMustBe(" world");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, CurlyBraces) {
|
||||
whenInputIs("\"{hello:world}\"");
|
||||
resultMustBe("{hello:world}");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, SquareBraquets) {
|
||||
whenInputIs("\"[hello,world]\"");
|
||||
resultMustBe("[hello,world]");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedDoubleQuote) {
|
||||
whenInputIs("\"hello \\\"world\\\"\"");
|
||||
resultMustBe("hello \"world\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedSingleQuote) {
|
||||
whenInputIs("\"hello \\\'world\\\'\"");
|
||||
resultMustBe("hello 'world'");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedSolidus) {
|
||||
whenInputIs("\"hello \\/world\\/\"");
|
||||
resultMustBe("hello /world/");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedReverseSolidus) {
|
||||
whenInputIs("\"hello \\\\world\\\\\"");
|
||||
resultMustBe("hello \\world\\");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedBackspace) {
|
||||
whenInputIs("\"hello \\bworld\\b\"");
|
||||
resultMustBe("hello \bworld\b");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedFormfeed) {
|
||||
whenInputIs("\"hello \\fworld\\f\"");
|
||||
resultMustBe("hello \fworld\f");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedNewline) {
|
||||
whenInputIs("\"hello \\nworld\\n\"");
|
||||
resultMustBe("hello \nworld\n");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedCarriageReturn) {
|
||||
whenInputIs("\"hello \\rworld\\r\"");
|
||||
resultMustBe("hello \rworld\r");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, EscapedTab) {
|
||||
whenInputIs("\"hello \\tworld\\t\"");
|
||||
resultMustBe("hello \tworld\t");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_ExtractFrom_Tests, AllEscapedCharsTogether) {
|
||||
whenInputIs("\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"");
|
||||
resultMustBe("1\"2\\3/4\b5\f6\n7\r8\t9");
|
||||
}
|
79
test/QuotedString_PrintTo_Tests.cpp
Normal file
79
test/QuotedString_PrintTo_Tests.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <ArduinoJson/Internals/QuotedString.hpp>
|
||||
#include <ArduinoJson/Internals/StringBuilder.hpp>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
class QuotedString_PrintTo_Tests : public testing::Test {
|
||||
protected:
|
||||
void whenInputIs(const char *input) {
|
||||
StringBuilder sb(buffer, sizeof(buffer));
|
||||
returnValue = QuotedString::printTo(input, sb);
|
||||
}
|
||||
|
||||
void outputMustBe(const char *expected) {
|
||||
EXPECT_STREQ(expected, buffer);
|
||||
EXPECT_EQ(strlen(expected), returnValue);
|
||||
}
|
||||
|
||||
private:
|
||||
char buffer[1024];
|
||||
size_t returnValue;
|
||||
};
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, Null) {
|
||||
whenInputIs(0);
|
||||
outputMustBe("null");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, EmptyString) {
|
||||
whenInputIs("");
|
||||
outputMustBe("\"\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, QuotationMark) {
|
||||
whenInputIs("\"");
|
||||
outputMustBe("\"\\\"\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, ReverseSolidus) {
|
||||
whenInputIs("\\");
|
||||
outputMustBe("\"\\\\\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, Solidus) {
|
||||
whenInputIs("/");
|
||||
outputMustBe("\"/\""); // but the JSON format allows \/
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, Backspace) {
|
||||
whenInputIs("\b");
|
||||
outputMustBe("\"\\b\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, Formfeed) {
|
||||
whenInputIs("\f");
|
||||
outputMustBe("\"\\f\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, Newline) {
|
||||
whenInputIs("\n");
|
||||
outputMustBe("\"\\n\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, CarriageReturn) {
|
||||
whenInputIs("\r");
|
||||
outputMustBe("\"\\r\"");
|
||||
}
|
||||
|
||||
TEST_F(QuotedString_PrintTo_Tests, HorizontalTab) {
|
||||
whenInputIs("\t");
|
||||
outputMustBe("\"\\t\"");
|
||||
}
|
45
test/StaticJsonBuffer_Array_Tests.cpp
Normal file
45
test/StaticJsonBuffer_Array_Tests.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(StaticJsonBuffer_Array_Tests, GrowsWithArray) {
|
||||
StaticJsonBuffer<JSON_ARRAY_SIZE(2)> json;
|
||||
|
||||
JsonArray &array = json.createArray();
|
||||
ASSERT_EQ(JSON_ARRAY_SIZE(0), json.size());
|
||||
|
||||
array.add("hello");
|
||||
ASSERT_EQ(JSON_ARRAY_SIZE(1), json.size());
|
||||
|
||||
array.add("world");
|
||||
ASSERT_EQ(JSON_ARRAY_SIZE(2), json.size());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_Array_Tests, SucceedWhenBigEnough) {
|
||||
StaticJsonBuffer<JSON_ARRAY_SIZE(0)> json;
|
||||
|
||||
JsonArray &array = json.createArray();
|
||||
ASSERT_TRUE(array.success());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_Array_Tests, FailsWhenTooSmall) {
|
||||
StaticJsonBuffer<JSON_ARRAY_SIZE(0) - 1> json;
|
||||
|
||||
JsonArray &array = json.createArray();
|
||||
ASSERT_FALSE(array.success());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_Array_Tests, ArrayDoesntGrowWhenFull) {
|
||||
StaticJsonBuffer<JSON_ARRAY_SIZE(1)> json;
|
||||
|
||||
JsonArray &array = json.createArray();
|
||||
array.add("hello");
|
||||
array.add("world");
|
||||
|
||||
EXPECT_EQ(1, array.size());
|
||||
}
|
59
test/StaticJsonBuffer_Basic_Tests.cpp
Normal file
59
test/StaticJsonBuffer_Basic_Tests.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#define protected public
|
||||
#include <ArduinoJson/StaticJsonBuffer.hpp>
|
||||
|
||||
using namespace ArduinoJson;
|
||||
|
||||
class StaticJsonBuffer_Basic_Tests : public testing::Test {
|
||||
protected:
|
||||
StaticJsonBuffer<42> buffer;
|
||||
};
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, CapacityMatchTemplateParameter) {
|
||||
ASSERT_EQ(42, buffer.capacity());
|
||||
}
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, InitialSizeIsZero) {
|
||||
ASSERT_EQ(0, buffer.size());
|
||||
}
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, GrowsAfterAlloc) {
|
||||
buffer.alloc(1);
|
||||
ASSERT_EQ(1, buffer.size());
|
||||
buffer.alloc(1);
|
||||
ASSERT_EQ(2, buffer.size());
|
||||
}
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, DoesntGrowWhenFull) {
|
||||
buffer.alloc(42);
|
||||
buffer.alloc(1);
|
||||
ASSERT_EQ(42, buffer.size());
|
||||
}
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, DoesntGrowWhenTooSmall) {
|
||||
buffer.alloc(43);
|
||||
ASSERT_EQ(0, buffer.size());
|
||||
}
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, ReturnsNonNull) {
|
||||
void *p = buffer.alloc(42);
|
||||
ASSERT_NE(static_cast<void *>(0), p);
|
||||
}
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, ReturnsNullWhenFull) {
|
||||
buffer.alloc(42);
|
||||
void *p = buffer.alloc(1);
|
||||
ASSERT_EQ(NULL, p);
|
||||
}
|
||||
|
||||
TEST_F(StaticJsonBuffer_Basic_Tests, ReturnsNullWhenTooSmall) {
|
||||
void *p = buffer.alloc(43);
|
||||
ASSERT_EQ(NULL, p);
|
||||
}
|
48
test/StaticJsonBuffer_Object_Tests.cpp
Normal file
48
test/StaticJsonBuffer_Object_Tests.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(StaticJsonBuffer_Object_Tests, GrowsWithObject) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> json;
|
||||
|
||||
JsonObject &obj = json.createObject();
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size());
|
||||
|
||||
obj["hello"];
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
|
||||
|
||||
obj["world"];
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
|
||||
|
||||
obj["world"]; // <- same value, should not grow
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_Object_Tests, SucceedWhenBigEnough) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> json;
|
||||
|
||||
JsonObject &object = json.createObject();
|
||||
ASSERT_TRUE(object.success());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_Object_Tests, FailsWhenTooSmall) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> json;
|
||||
|
||||
JsonObject &object = json.createObject();
|
||||
ASSERT_FALSE(object.success());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_Object_Tests, ObjectDoesntGrowWhenFull) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> json;
|
||||
|
||||
JsonObject &obj = json.createObject();
|
||||
obj["hello"];
|
||||
obj["world"];
|
||||
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user