mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-06-28 19:01:01 +02:00
Compare commits
367 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 |
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,6 +1,5 @@
|
||||
*.sdf
|
||||
*.user
|
||||
*.suo
|
||||
Debug
|
||||
ipch
|
||||
*.opensdf
|
||||
.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
|
@ -1,40 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonGeneratorTests", "JsonGeneratorTests\JsonGeneratorTests.vcxproj", "{B9545D97-E084-4A19-8E48-929157064360}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonParserTests", "JsonParserTests\JsonParserTests.vcxproj", "{4DD596EF-0185-4AB4-A3C2-F20C496F7806}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonParser", "JsonParser\JsonParser.vcxproj", "{C15274DE-2695-4DFE-8520-4424223FE6DA}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonGenerator", "JsonGenerator\JsonGenerator.vcxproj", "{C6536D27-738D-4CEB-A2BC-E13C8897D894}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B9545D97-E084-4A19-8E48-929157064360}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B9545D97-E084-4A19-8E48-929157064360}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B9545D97-E084-4A19-8E48-929157064360}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B9545D97-E084-4A19-8E48-929157064360}.Release|Win32.Build.0 = Release|Win32
|
||||
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4DD596EF-0185-4AB4-A3C2-F20C496F7806}.Release|Win32.Build.0 = Release|Win32
|
||||
{C15274DE-2695-4DFE-8520-4424223FE6DA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{C15274DE-2695-4DFE-8520-4424223FE6DA}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C15274DE-2695-4DFE-8520-4424223FE6DA}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{C15274DE-2695-4DFE-8520-4424223FE6DA}.Release|Win32.Build.0 = Release|Win32
|
||||
{C6536D27-738D-4CEB-A2BC-E13C8897D894}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{C6536D27-738D-4CEB-A2BC-E13C8897D894}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C6536D27-738D-4CEB-A2BC-E13C8897D894}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{C6536D27-738D-4CEB-A2BC-E13C8897D894}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
ZIP="C:\Program Files\7-Zip\7z.exe"
|
||||
|
||||
TAG=$(git describe)
|
||||
OUTPUT="ArduinoJson-$TAG.zip"
|
||||
|
||||
cd ..
|
||||
|
||||
INPUT=$(find ArduinoJson -regex ".*\.\(cpp\|h\|md\|txt\|ino\)$" -not -regex ".*Tests/.*")
|
||||
|
||||
rm -f $OUTPUT
|
||||
"$ZIP" a $OUTPUT $INPUT
|
31
CHANGELOG.md
31
CHANGELOG.md
@ -1,6 +1,33 @@
|
||||
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
|
||||
----
|
||||
|
||||
@ -11,7 +38,7 @@ 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()`
|
||||
* Added `Generator::JsonObject::remove()` (issue #9)
|
||||
|
||||
Old generator API:
|
||||
|
||||
@ -32,7 +59,7 @@ v3.0
|
||||
|
||||
* New parser API, see bellow
|
||||
* Renamed `JsonHashTable` into `JsonObject`
|
||||
* Added iterators for `JsonArray` and `JsonObject`
|
||||
* Added iterators for `JsonArray` and `JsonObject` (issue #4)
|
||||
|
||||
Old parser API:
|
||||
|
||||
|
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,12 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
// This file is here to help the Arduino IDE find the .cpp files
|
||||
|
||||
#include "JsonGenerator/EscapedString.cpp"
|
||||
#include "JsonGenerator/JsonArrayBase.cpp"
|
||||
#include "JsonGenerator/JsonObjectBase.cpp"
|
||||
#include "JsonGenerator/JsonValue.cpp"
|
||||
#include "JsonGenerator/StringBuilder.cpp"
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonGenerator/JsonArray.h"
|
||||
#include "JsonGenerator/JsonObject.h"
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "EscapedString.h"
|
||||
|
||||
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 != 0
|
||||
? p.write('\\') + p.write(specialChar)
|
||||
: p.write(c);
|
||||
}
|
||||
|
||||
size_t EscapedString::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('\"');
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Internals
|
||||
{
|
||||
class EscapedString
|
||||
{
|
||||
public:
|
||||
static size_t printTo(const char*, Print&);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArrayBase.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Generator
|
||||
{
|
||||
template<int N>
|
||||
class JsonArray : public JsonArrayBase
|
||||
{
|
||||
public:
|
||||
JsonArray()
|
||||
: JsonArrayBase(items, N)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
JsonValue items[N];
|
||||
};
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonArrayBase.h"
|
||||
|
||||
using namespace ArduinoJson::Generator;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
size_t JsonArrayBase::printTo(Print& p) const
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
n += p.write('[');
|
||||
|
||||
// NB: the code has been optimized for a small size on a 8-bit AVR
|
||||
|
||||
const JsonValue* current = items;
|
||||
for (int i = count; i > 0; i--)
|
||||
{
|
||||
n += current->printTo(p);
|
||||
current++;
|
||||
|
||||
if (i > 1)
|
||||
{
|
||||
n += p.write(',');
|
||||
}
|
||||
}
|
||||
|
||||
n += p.write(']');
|
||||
|
||||
return n;
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonPrintable.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Generator
|
||||
{
|
||||
class JsonArrayBase : public JsonPrintable
|
||||
{
|
||||
public:
|
||||
JsonArrayBase(JsonValue* items, int capacity)
|
||||
: items(items), capacity(capacity), count(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void add(const Printable& value)
|
||||
{
|
||||
addIfPossible<const Printable&>(value);
|
||||
}
|
||||
|
||||
void add(bool value)
|
||||
{
|
||||
addIfPossible<bool>(value);
|
||||
}
|
||||
|
||||
void add(int value)
|
||||
{
|
||||
addIfPossible<long>(value);
|
||||
}
|
||||
|
||||
void add(long value)
|
||||
{
|
||||
addIfPossible<long>(value);
|
||||
}
|
||||
|
||||
void add(double value)
|
||||
{
|
||||
addIfPossible<double>(value);
|
||||
}
|
||||
|
||||
void add(const char* value)
|
||||
{
|
||||
addIfPossible<const char*>(value);
|
||||
}
|
||||
|
||||
template<int DIGITS>
|
||||
void add(double value)
|
||||
{
|
||||
if (count >= capacity) return;
|
||||
|
||||
JsonValue& v = items[count++];
|
||||
v.set<DIGITS>(value);
|
||||
}
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
|
||||
using JsonPrintable::printTo;
|
||||
|
||||
private:
|
||||
JsonValue* items;
|
||||
int capacity, count;
|
||||
|
||||
template<typename T>
|
||||
void addIfPossible(T value)
|
||||
{
|
||||
if (count < capacity)
|
||||
items[count++] = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="EscapedString.h" />
|
||||
<ClInclude Include="JsonArray.h" />
|
||||
<ClInclude Include="JsonArrayBase.h" />
|
||||
<ClInclude Include="JsonObject.h" />
|
||||
<ClInclude Include="JsonObjectBase.h" />
|
||||
<ClInclude Include="JsonPrintable.h" />
|
||||
<ClInclude Include="JsonValue.h" />
|
||||
<ClInclude Include="Print.h" />
|
||||
<ClInclude Include="Printable.h" />
|
||||
<ClInclude Include="StringBuilder.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="EscapedString.cpp" />
|
||||
<ClCompile Include="JsonArrayBase.cpp" />
|
||||
<ClCompile Include="JsonObjectBase.cpp" />
|
||||
<ClCompile Include="JsonValue.cpp" />
|
||||
<ClCompile Include="Print.cpp" />
|
||||
<ClCompile Include="StringBuilder.cpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C6536D27-738D-4CEB-A2BC-E13C8897D894}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>JsonGenerator</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="EscapedString.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonArray.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonArrayBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonPrintable.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonValue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Print.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Printable.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringBuilder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonObjectBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonObject.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="EscapedString.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonArrayBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonValue.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringBuilder.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Print.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonObjectBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonObjectBase.h"
|
||||
|
||||
#ifndef ARDUINO_JSON_NO_DEPRECATION_WARNING
|
||||
#ifdef __GNUC__
|
||||
#define DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEPRECATED __declspec(deprecated)
|
||||
#endif
|
||||
#else
|
||||
#define DEPRECATED
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Generator
|
||||
{
|
||||
template <int N>
|
||||
class JsonObject : public JsonObjectBase
|
||||
{
|
||||
public:
|
||||
JsonObject()
|
||||
: JsonObjectBase(items, N)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
KeyValuePair items[N];
|
||||
};
|
||||
|
||||
|
||||
// Obsolete: use JsonObject instead
|
||||
template <int N>
|
||||
class DEPRECATED JsonHashTable : public JsonObject<N>
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonObjectBase.h"
|
||||
#include <string.h> // for strcmp
|
||||
|
||||
using namespace ArduinoJson::Generator;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
JsonValue JsonObjectBase::nullValue;
|
||||
|
||||
size_t JsonObjectBase::printTo(Print& p) const
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
n += p.write('{');
|
||||
|
||||
// NB: the code has been optimized for a small size on a 8-bit AVR
|
||||
|
||||
const KeyValuePair* current = items;
|
||||
for (int i = count; i > 0; i--)
|
||||
{
|
||||
n += EscapedString::printTo(current->key, p);
|
||||
n += p.write(':');
|
||||
n += current->value.printTo(p);
|
||||
|
||||
current++;
|
||||
|
||||
if (i > 1)
|
||||
{
|
||||
n += p.write(',');
|
||||
}
|
||||
}
|
||||
|
||||
n += p.write('}');
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
JsonObjectBase::KeyValuePair* JsonObjectBase::getMatchingPair(JsonKey key) const
|
||||
{
|
||||
KeyValuePair* p = items;
|
||||
|
||||
for (int i = count; i > 0; --i)
|
||||
{
|
||||
if (!strcmp(p->key, key))
|
||||
return p;
|
||||
|
||||
p++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
JsonValue& JsonObjectBase::operator[](JsonKey key)
|
||||
{
|
||||
KeyValuePair* match = getMatchingPair(key);
|
||||
|
||||
if (match)
|
||||
return match->value;
|
||||
|
||||
JsonValue* value;
|
||||
|
||||
if (count < capacity)
|
||||
{
|
||||
items[count].key = key;
|
||||
value = &items[count].value;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = &nullValue;
|
||||
}
|
||||
|
||||
value->reset();
|
||||
return *value;
|
||||
}
|
||||
|
||||
bool JsonObjectBase::containsKey(JsonKey key) const
|
||||
{
|
||||
return getMatchingPair(key) != 0;
|
||||
}
|
||||
|
||||
void JsonObjectBase::remove(JsonKey key)
|
||||
{
|
||||
KeyValuePair* match = getMatchingPair(key);
|
||||
if (match == 0) return;
|
||||
|
||||
*match = items[--count];
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonPrintable.h"
|
||||
#include "EscapedString.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Generator
|
||||
{
|
||||
typedef const char* JsonKey;
|
||||
|
||||
class JsonObjectBase : public JsonPrintable
|
||||
{
|
||||
public:
|
||||
JsonValue& operator[](JsonKey);
|
||||
bool containsKey(JsonKey) const;
|
||||
void remove(JsonKey key);
|
||||
|
||||
template<typename T>
|
||||
void add(JsonKey key, T value)
|
||||
{
|
||||
operator[](key) = value;
|
||||
}
|
||||
|
||||
template<int DIGITS>
|
||||
void add(JsonKey key, double value)
|
||||
{
|
||||
operator[](key).set<DIGITS>(value);
|
||||
}
|
||||
|
||||
using JsonPrintable::printTo;
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
|
||||
protected:
|
||||
|
||||
struct KeyValuePair
|
||||
{
|
||||
JsonKey key;
|
||||
JsonValue value;
|
||||
};
|
||||
|
||||
JsonObjectBase(KeyValuePair* items, int capacity)
|
||||
: items(items), capacity(capacity), count(0)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
KeyValuePair* items;
|
||||
int capacity, count;
|
||||
static JsonValue nullValue;
|
||||
|
||||
KeyValuePair* getMatchingPair(JsonKey key) const;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonValue.h"
|
||||
#include "Print.h"
|
||||
#include "Printable.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Generator
|
||||
{
|
||||
class JsonPrintable : public Printable
|
||||
{
|
||||
public:
|
||||
|
||||
size_t printTo(char* buffer, size_t bufferSize)
|
||||
{
|
||||
using namespace Internals;
|
||||
|
||||
StringBuilder sb(buffer, bufferSize);
|
||||
return printTo(sb);
|
||||
}
|
||||
|
||||
virtual size_t printTo(Print& p) const = 0;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "EscapedString.h"
|
||||
#include "JsonValue.h"
|
||||
|
||||
using namespace ArduinoJson::Generator;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
size_t JsonValue::printBoolTo(const Content& c, Print& p)
|
||||
{
|
||||
return p.print(c.asBool ? "true" : "false");
|
||||
}
|
||||
|
||||
size_t JsonValue::printLongTo(const Content& c, Print& p)
|
||||
{
|
||||
return p.print(c.asLong);
|
||||
}
|
||||
|
||||
size_t JsonValue::printPrintableTo(const Content& c, Print& p)
|
||||
{
|
||||
if (c.asPrintable)
|
||||
return c.asPrintable->printTo(p);
|
||||
else
|
||||
return p.print("null");
|
||||
}
|
||||
|
||||
size_t JsonValue::printStringTo(const Content& c, Print& p)
|
||||
{
|
||||
return EscapedString::printTo(c.asString, p);
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "EscapedString.h"
|
||||
#include "Printable.h"
|
||||
#include "StringBuilder.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Generator
|
||||
{
|
||||
class JsonValue
|
||||
{
|
||||
public:
|
||||
|
||||
void operator=(bool value)
|
||||
{
|
||||
printToImpl = &printBoolTo;
|
||||
content.asBool = value;
|
||||
}
|
||||
|
||||
void operator=(long value)
|
||||
{
|
||||
printToImpl = &printLongTo;
|
||||
content.asLong = value;
|
||||
}
|
||||
|
||||
void operator=(int value)
|
||||
{
|
||||
printToImpl = &printLongTo;
|
||||
content.asLong = value;
|
||||
}
|
||||
|
||||
void operator=(const Printable& value)
|
||||
{
|
||||
printToImpl = &printPrintableTo;
|
||||
content.asPrintable = &value;
|
||||
}
|
||||
|
||||
void operator=(const char* value)
|
||||
{
|
||||
printToImpl = &printStringTo;
|
||||
content.asString = value;
|
||||
}
|
||||
|
||||
void operator=(double value)
|
||||
{
|
||||
set<2>(value);
|
||||
}
|
||||
|
||||
template <int DIGITS>
|
||||
void set(double value)
|
||||
{
|
||||
printToImpl = &printDoubleTo < DIGITS > ;
|
||||
content.asDouble = value;
|
||||
}
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return content.asBool;
|
||||
}
|
||||
|
||||
operator const char*()
|
||||
{
|
||||
return content.asString;
|
||||
}
|
||||
|
||||
operator double()
|
||||
{
|
||||
return content.asDouble;
|
||||
}
|
||||
|
||||
operator float()
|
||||
{
|
||||
return (float)content.asDouble;
|
||||
}
|
||||
|
||||
operator int()
|
||||
{
|
||||
return content.asLong;
|
||||
}
|
||||
|
||||
operator long()
|
||||
{
|
||||
return content.asLong;
|
||||
}
|
||||
|
||||
operator const Printable&()
|
||||
{
|
||||
return *content.asPrintable;
|
||||
}
|
||||
|
||||
size_t printTo(Print& p) const
|
||||
{
|
||||
// handmade polymorphism
|
||||
return printToImpl(content, p);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
content.asDouble = 0;
|
||||
printToImpl = printStringTo;
|
||||
}
|
||||
|
||||
private:
|
||||
union Content
|
||||
{
|
||||
bool asBool;
|
||||
double asDouble;
|
||||
long asLong;
|
||||
const Printable* asPrintable;
|
||||
const char* asString;
|
||||
};
|
||||
|
||||
Content content;
|
||||
|
||||
size_t(*printToImpl)(const Content&, Print&);
|
||||
|
||||
static size_t printBoolTo(const Content&, Print&);
|
||||
static size_t printLongTo(const Content&, Print&);
|
||||
static size_t printPrintableTo(const Content&, Print&);
|
||||
static size_t printStringTo(const Content&, Print&);
|
||||
|
||||
template <int DIGITS>
|
||||
static size_t printDoubleTo(const Content& c, Print& p)
|
||||
{
|
||||
return p.print(c.asDouble, DIGITS);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
#include "Print.h"
|
||||
#include <cstdio>
|
||||
|
||||
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, "%.*lg", digits+1, value);
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
size_t Print::print(long value)
|
||||
{
|
||||
char tmp[32];
|
||||
sprintf(tmp, "%ld", value);
|
||||
return print(tmp);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
|
||||
// This class reproduces Arduino's Print
|
||||
class Print
|
||||
{
|
||||
public:
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
|
||||
size_t print(const char[]);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(long);
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <Print.h>
|
||||
|
||||
#endif
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef ARDUINO
|
||||
|
||||
class Print;
|
||||
|
||||
class Printable
|
||||
{
|
||||
public:
|
||||
|
||||
virtual size_t printTo(Print& p) const = 0;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#include <Printable.h>
|
||||
|
||||
#endif
|
||||
|
@ -1,239 +0,0 @@
|
||||
Arduino JSON library - Generator
|
||||
================================
|
||||
|
||||
*An elegant and efficient JSON encoder for embedded systems.*
|
||||
|
||||
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
|
||||
--------
|
||||
|
||||
* Elegant API, very easy to use
|
||||
* Fixed memory allocation (no malloc)
|
||||
* Small footprint
|
||||
* Supports nested objects
|
||||
* Implements Arduino's `Printable interface
|
||||
* MIT License
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
JsonArray<2> array;
|
||||
array.add<6>(48.756080); // <6> specifies the number of digits in the output
|
||||
array.add<6>(2.302038); // (the default is 2)
|
||||
|
||||
JsonObject<3> root;
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
root["data"] = array;
|
||||
|
||||
Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
|
||||
How to use?
|
||||
------------
|
||||
|
||||
### 1. Install the library
|
||||
|
||||
Download the library and extract it to:
|
||||
|
||||
<your Arduino Sketch folder>/libraries/ArduinoJson
|
||||
|
||||
### 2. Import in your sketch
|
||||
|
||||
Just add the following lines at the top of your `.ino` file:
|
||||
|
||||
#include <JsonGenerator.h>
|
||||
|
||||
using namespace ArduinoJson::Generator;
|
||||
|
||||
> ##### Having a namespace conflict?
|
||||
> To be able to use both `ArduinoJson::Generator` and `ArduinoJson::Parser` in the same file, you need to do one of the followings:
|
||||
>
|
||||
> * Put the `using` statements into different functions
|
||||
> * `using namespace ArduinoJson`, then prefix the type names by `Generator::` or `Parser::`
|
||||
> * Create aliases for the namespaces or the types (C++11 only)
|
||||
|
||||
### 3. Create object tree
|
||||
|
||||
In order to generate a JSON string, you need to build the equivalent object tree. You usually start by the root which can be either a JSON Array or a JSON Object.
|
||||
|
||||
#### JSON Array
|
||||
|
||||
You create an array with the following line:
|
||||
|
||||
JsonArray<8> array;
|
||||
|
||||
See the little `<8>`? It's a template parameter that gives the capacity of the array, it's the maximum number of elements you can put in it.
|
||||
|
||||
> ##### About the capacity
|
||||
> As stated in the feature list, this library works with a fixed memory allocation.
|
||||
> This means that the size of the object must be know at the compilation time, therefore you can **not** use a variable to set the capacity of 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<4>(3.1415); // 4 digits: "3.1415"
|
||||
array.add(3.14); // 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 two.
|
||||
> 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 it.
|
||||
|
||||
Finally you can add nested object to the array:
|
||||
|
||||
JsonArray<8> nestedArray;
|
||||
array.add(nestedArray);
|
||||
|
||||
or
|
||||
|
||||
JsonObject<8> nestedObject;
|
||||
array.add(nestedObject);
|
||||
|
||||
> ##### CAUTION! Nested objects must be in memory
|
||||
> Calling `add()` makes the `JsonArray` store a pointer to the nested object.
|
||||
> This is designed to avoid memory duplication.
|
||||
> But it can only work if the object is in memory when `printTo()` is executed.
|
||||
> For instance, don't do this:
|
||||
>
|
||||
> void addNestedObject()
|
||||
> {
|
||||
> JsonObject<2> nestedObject;
|
||||
> // ...
|
||||
> array.add(nestedObject); // <- DON'T !!
|
||||
>
|
||||
> // array now contains a pointer to a local variable that will be
|
||||
> // discarded as soon as the function exits
|
||||
> }
|
||||
>
|
||||
> For the same reason, don't do this either:
|
||||
>
|
||||
> for( int i=0; i<100; i++)
|
||||
> {
|
||||
> JsonObject<2> nestedObject;
|
||||
> // ...
|
||||
> array.add(nestedObject); // <- DON'T !!
|
||||
> }
|
||||
> // array now contains 100 pointers to the same a local variable
|
||||
> // that is out of the scope anyway
|
||||
|
||||
#### JSON Object
|
||||
|
||||
You create a JSON object (ie hash-table/dictionary) with the following line:
|
||||
|
||||
JsonObject<8> object;
|
||||
|
||||
Like with the array class, there is a template parameter that gives the capacity of 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<4>(3.1415); // 4 digits "3.1415"
|
||||
object["key5"] = 3.1415; // default: 2 digits "3.14"
|
||||
|
||||
Finally you can add nested objects:
|
||||
|
||||
JsonArray<8> nestedArray;
|
||||
object["key6"] = nestedArray;
|
||||
|
||||
or
|
||||
|
||||
JsonObject<8> nestedObject;
|
||||
object["key7"] = nestedObject;
|
||||
|
||||
> ##### 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`
|
||||
|
||||
### 4. Get 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 stream 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));
|
||||
|
||||
#### Send to a stream
|
||||
|
||||
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:
|
||||
|
||||
Serial.print(array);
|
||||
|
||||
or
|
||||
|
||||
array.printTo(Serial);
|
||||
|
||||
> ##### About the Printable interface
|
||||
> `JsonArray` and `JsonObject` implement Arduino's `Printable` interface.
|
||||
> This is why you can call `Serial.print()` like in the example above.
|
||||
> You can do the same with any other implementation of `Print`: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`...
|
||||
|
||||
|
||||
Memory usage
|
||||
------------
|
||||
|
||||
Here are the size of the main classes of the library.
|
||||
|
||||
This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor.
|
||||
|
||||
| Type | Size in bytes |
|
||||
| --------------------| ------------- |
|
||||
| JsonArray<N> | 8 + 6 x N |
|
||||
| JsonObject<N> | 8 + 8 x N |
|
||||
|
||||
|
||||
Code size
|
||||
---------
|
||||
|
||||
The following values has been obtained with Arduino IDE 1.0.5, targeting an Arduino Duelmilanove with an ATmega 328.
|
||||
|
||||
### Minimum setup
|
||||
|
||||
| Function | Size |
|
||||
| ----------------------------------- | ---- |
|
||||
| `JsonObjectBase::printTo()` | 234 |
|
||||
| `EscapedString::printTo()` | 196 |
|
||||
| `JsonArrayBase::printTo()` | 164 |
|
||||
| `Print::print(char const*)` | 146 |
|
||||
| `JsonObjectBase::operator[]` | 114 |
|
||||
| `JsonObjectBase::getMatchingPair()` | 72 |
|
||||
| `JsonValue::printPrintableTo()` | 40 |
|
||||
| `JsonValue::printStringTo()` | 12 |
|
||||
|
||||
### Additional space for integers
|
||||
|
||||
| Function | Size |
|
||||
| ---------------------------- | ---- |
|
||||
| `Print::print(long, int)` | 328 |
|
||||
| `JsonValue::printLongTo()` | 22 |
|
||||
|
||||
### Additional space for floating point
|
||||
|
||||
| Function | Size |
|
||||
| ------------------------------ | ---- |
|
||||
| `Print::print(double, int)` | 1548 |
|
||||
| `JsonValue::printDouleTo<2>()` | 22 |
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "StringBuilder.h"
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
size_t StringBuilder::write(uint8_t c)
|
||||
{
|
||||
if (length >= capacity) return 0;
|
||||
|
||||
buffer[length++] = c;
|
||||
buffer[length] = 0;
|
||||
return 1;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Internals
|
||||
{
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "EscapedString.h"
|
||||
#include "StringBuilder.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(EscapedStringTests)
|
||||
{
|
||||
char buffer[1024];
|
||||
size_t returnValue;
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(Null)
|
||||
{
|
||||
whenInputIs(0);
|
||||
outputMustBe("null");
|
||||
}
|
||||
|
||||
TEST_METHOD(EmptyString)
|
||||
{
|
||||
whenInputIs("");
|
||||
outputMustBe("\"\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(QuotationMark)
|
||||
{
|
||||
whenInputIs("\"");
|
||||
outputMustBe("\"\\\"\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(ReverseSolidus)
|
||||
{
|
||||
whenInputIs("\\");
|
||||
outputMustBe("\"\\\\\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(Solidus)
|
||||
{
|
||||
whenInputIs("/");
|
||||
outputMustBe("\"/\""); // but the JSON format allows \/
|
||||
}
|
||||
|
||||
TEST_METHOD(Backspace)
|
||||
{
|
||||
whenInputIs("\b");
|
||||
outputMustBe("\"\\b\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(Formfeed)
|
||||
{
|
||||
whenInputIs("\f");
|
||||
outputMustBe("\"\\f\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(Newline)
|
||||
{
|
||||
whenInputIs("\n");
|
||||
outputMustBe("\"\\n\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(CarriageReturn)
|
||||
{
|
||||
whenInputIs("\r");
|
||||
outputMustBe("\"\\r\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(HorizontalTab)
|
||||
{
|
||||
whenInputIs("\t");
|
||||
outputMustBe("\"\\t\"");
|
||||
}
|
||||
|
||||
private:
|
||||
void whenInputIs(const char* input)
|
||||
{
|
||||
StringBuilder sb(buffer, sizeof(buffer));
|
||||
returnValue = EscapedString::printTo(input, sb);
|
||||
}
|
||||
|
||||
void outputMustBe(const char* expected)
|
||||
{
|
||||
Assert::AreEqual(expected, buffer);
|
||||
Assert::AreEqual(strlen(expected), returnValue);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
|
||||
using namespace ArduinoJson::Generator;
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(Issue10)
|
||||
{
|
||||
struct Person {
|
||||
int id;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
Person persons[2];
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD_INITIALIZE(Initialize)
|
||||
{
|
||||
Person boss;
|
||||
boss.id = 1;
|
||||
strcpy(boss.name, "Jeff");
|
||||
Person employee;
|
||||
employee.id = 2;
|
||||
strcpy(employee.name, "John");
|
||||
persons[0] = boss;
|
||||
persons[1] = employee;
|
||||
}
|
||||
|
||||
TEST_METHOD(WrongWayToAddObjectInAnArray)
|
||||
{
|
||||
JsonArray<2> json;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
JsonObject<2> object;
|
||||
|
||||
object["id"] = persons[i].id;
|
||||
object["name"] = persons[i].name;
|
||||
|
||||
json.add(object); // <- Adding a reference to a temporary variable
|
||||
}
|
||||
|
||||
char buffer[256];
|
||||
json.printTo(buffer, sizeof(buffer));
|
||||
|
||||
// the same values are repeated, that's normal
|
||||
Assert::AreEqual("[{\"id\":2,\"name\":\"John\"},{\"id\":2,\"name\":\"John\"}]", buffer);
|
||||
}
|
||||
|
||||
TEST_METHOD(RightWayToAddObjectInAnArray)
|
||||
{
|
||||
JsonArray<2> json;
|
||||
JsonObject<2> object[2];
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
object[i]["id"] = persons[i].id;
|
||||
object[i]["name"] = persons[i].name;
|
||||
|
||||
json.add(object[i]);
|
||||
}
|
||||
|
||||
char buffer[256];
|
||||
json.printTo(buffer, sizeof(buffer));
|
||||
|
||||
Assert::AreEqual("[{\"id\":1,\"name\":\"Jeff\"},{\"id\":2,\"name\":\"John\"}]", buffer);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Generator;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(JsonArrayTests)
|
||||
{
|
||||
JsonArray<2> array;
|
||||
char buffer[256];
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(Empty)
|
||||
{
|
||||
outputMustBe("[]");
|
||||
}
|
||||
|
||||
TEST_METHOD(Null)
|
||||
{
|
||||
array.add((char*) 0);
|
||||
|
||||
outputMustBe("[null]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneString)
|
||||
{
|
||||
array.add("hello");
|
||||
|
||||
outputMustBe("[\"hello\"]");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoStrings)
|
||||
{
|
||||
array.add("hello");
|
||||
array.add("world");
|
||||
|
||||
outputMustBe("[\"hello\",\"world\"]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneStringOverCapacity)
|
||||
{
|
||||
array.add("hello");
|
||||
array.add("world");
|
||||
array.add("lost");
|
||||
|
||||
outputMustBe("[\"hello\",\"world\"]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneDoubleDefaultDigits)
|
||||
{
|
||||
array.add(3.14159265358979323846);
|
||||
outputMustBe("[3.14]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneDoubleFourDigits)
|
||||
{
|
||||
array.add<4>(3.14159265358979323846);
|
||||
outputMustBe("[3.1416]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneInteger)
|
||||
{
|
||||
array.add(1);
|
||||
|
||||
outputMustBe("[1]");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoIntegers)
|
||||
{
|
||||
array.add(1);
|
||||
array.add(2);
|
||||
|
||||
outputMustBe("[1,2]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneIntegerOverCapacity)
|
||||
{
|
||||
array.add(1);
|
||||
array.add(2);
|
||||
array.add(3);
|
||||
|
||||
outputMustBe("[1,2]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneTrue)
|
||||
{
|
||||
array.add(true);
|
||||
|
||||
outputMustBe("[true]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneFalse)
|
||||
{
|
||||
array.add(false);
|
||||
|
||||
outputMustBe("[false]");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoBooleans)
|
||||
{
|
||||
array.add(false);
|
||||
array.add(true);
|
||||
|
||||
outputMustBe("[false,true]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneBooleanOverCapacity)
|
||||
{
|
||||
array.add(false);
|
||||
array.add(true);
|
||||
array.add(false);
|
||||
|
||||
outputMustBe("[false,true]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneEmptyNestedArray)
|
||||
{
|
||||
JsonArray<1> nestedArray;
|
||||
|
||||
array.add(nestedArray);
|
||||
|
||||
outputMustBe("[[]]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneEmptyNestedHash)
|
||||
{
|
||||
JsonObject<1> nestedObject;
|
||||
|
||||
array.add(nestedObject);
|
||||
|
||||
outputMustBe("[{}]");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneNestedArrayWithOneInteger)
|
||||
{
|
||||
JsonArray<1> nestedArray;
|
||||
nestedArray.add(1);
|
||||
|
||||
array.add(nestedArray);
|
||||
|
||||
outputMustBe("[[1]]");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void outputMustBe(const char* expected)
|
||||
{
|
||||
size_t n = array.printTo(buffer, sizeof(buffer));
|
||||
Assert::AreEqual(expected, buffer);
|
||||
Assert::AreEqual(strlen(expected), n);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{B9545D97-E084-4A19-8E48-929157064360}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>JsonGeneratorTests</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(ProjectDir)/../JsonGenerator;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(ProjectDir)/../JsonGenerator;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ARDUINO_JSON_NO_DEPRECATION_WARNING;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="EscapedStringTests.cpp" />
|
||||
<ClCompile Include="Issue10.cpp" />
|
||||
<ClCompile Include="JsonArrayTests.cpp" />
|
||||
<ClCompile Include="JsonObject_Indexer_Tests.cpp" />
|
||||
<ClCompile Include="JsonObject_PrintTo_Tests.cpp" />
|
||||
<ClCompile Include="JsonValue_Cast_Tests.cpp" />
|
||||
<ClCompile Include="JsonValue_PrintTo_Tests.cpp" />
|
||||
<ClCompile Include="StringBuilderTests.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\JsonGenerator\JsonGenerator.vcxproj">
|
||||
<Project>{c6536d27-738d-4ceb-a2bc-e13c8897d894}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="JsonArrayTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringBuilderTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EscapedStringTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonObject_PrintTo_Tests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonObject_Indexer_Tests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonValue_PrintTo_Tests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonValue_Cast_Tests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Issue10.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Generator;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(JsonObject_Indexer_Tests)
|
||||
{
|
||||
JsonObject<2> object;
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(Empty)
|
||||
{
|
||||
mustNotContain("key");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoStrings)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
|
||||
mustContain("key1", "value1");
|
||||
mustContain("key2", "value2");
|
||||
}
|
||||
|
||||
TEST_METHOD(RemoveFirst)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key1");
|
||||
|
||||
mustNotContain("key1");
|
||||
mustContain("key2", "value2");
|
||||
}
|
||||
|
||||
TEST_METHOD(RemoveLast)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key2");
|
||||
|
||||
mustContain("key1", "value1");
|
||||
mustNotContain("key2");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void mustContain(const char* key, const char* expected)
|
||||
{
|
||||
Assert::IsTrue(object.containsKey(key));
|
||||
|
||||
const char* actual = object[key];
|
||||
Assert::AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
void mustNotContain(const char* key)
|
||||
{
|
||||
Assert::IsFalse(object.containsKey(key));
|
||||
|
||||
const char* actual = object[key];
|
||||
Assert::IsNull(actual);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Generator;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(JsonObject_PrintTo_Tests)
|
||||
{
|
||||
JsonObject<2> object;
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(Empty)
|
||||
{
|
||||
outputMustBe("{}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneString)
|
||||
{
|
||||
object["key"] = "value";
|
||||
|
||||
outputMustBe("{\"key\":\"value\"}");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoStrings)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_METHOD(RemoveFirst)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key1");
|
||||
|
||||
outputMustBe("{\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_METHOD(RemoveLast)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key2");
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\"}");
|
||||
}
|
||||
|
||||
TEST_METHOD(RemoveUnexistingKey)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key3");
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_METHOD(ReplaceExistingKey)
|
||||
{
|
||||
object["key"] = "value1";
|
||||
object["key"] = "value2";
|
||||
|
||||
outputMustBe("{\"key\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneStringOverCapacity)
|
||||
{
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object["key3"] = "value3";
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneInteger)
|
||||
{
|
||||
object["key"] = 1;
|
||||
outputMustBe("{\"key\":1}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneDoubleFourDigits)
|
||||
{
|
||||
object["key"].set<4>(3.14159265358979323846);
|
||||
outputMustBe("{\"key\":3.1416}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneDoubleDefaultDigits)
|
||||
{
|
||||
object["key"] = 3.14159265358979323846;
|
||||
outputMustBe("{\"key\":3.14}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneNull)
|
||||
{
|
||||
object["key"] = (char*) 0;
|
||||
outputMustBe("{\"key\":null}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneTrue)
|
||||
{
|
||||
object["key"] = true;
|
||||
outputMustBe("{\"key\":true}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneFalse)
|
||||
{
|
||||
object["key"] = false;
|
||||
outputMustBe("{\"key\":false}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneEmptyNestedArray)
|
||||
{
|
||||
auto nestedArray = JsonArray<1>();
|
||||
|
||||
object["key"] = nestedArray;
|
||||
|
||||
outputMustBe("{\"key\":[]}");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneEmptyNestedObject)
|
||||
{
|
||||
auto nestedObject = JsonObject<1>();
|
||||
|
||||
object["key"] = nestedObject;
|
||||
|
||||
outputMustBe("{\"key\":{}}");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void outputMustBe(const char* expected)
|
||||
{
|
||||
char buffer[256];
|
||||
size_t result;
|
||||
|
||||
result = object.printTo(buffer, sizeof(buffer));
|
||||
|
||||
Assert::AreEqual(strlen(expected), result);
|
||||
Assert::AreEqual(expected, buffer);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "StringBuilder.h"
|
||||
#include "JsonValue.h"
|
||||
#include "JsonArray.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Generator;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(JsonValue_Cast_Tests)
|
||||
{
|
||||
JsonValue value;
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(Bool)
|
||||
{
|
||||
setValueAndCheckCast(true);
|
||||
setValueAndCheckCast(false);
|
||||
}
|
||||
|
||||
TEST_METHOD(Double)
|
||||
{
|
||||
setValueAndCheckCast(3.14156);
|
||||
}
|
||||
|
||||
TEST_METHOD(Float)
|
||||
{
|
||||
setValueAndCheckCast(3.14f);
|
||||
}
|
||||
|
||||
TEST_METHOD(Integer)
|
||||
{
|
||||
setValueAndCheckCast(42);
|
||||
}
|
||||
|
||||
TEST_METHOD(Long)
|
||||
{
|
||||
setValueAndCheckCast(42L);
|
||||
}
|
||||
|
||||
TEST_METHOD(Array)
|
||||
{
|
||||
JsonArray<2> array;
|
||||
setValueAndCheckCast(array);
|
||||
}
|
||||
|
||||
TEST_METHOD(String)
|
||||
{
|
||||
setValueAndCheckCast("hello");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
void setValueAndCheckCast(T expected)
|
||||
{
|
||||
value = expected;
|
||||
T actual = value;
|
||||
Assert::AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
template<int N>
|
||||
void setValueAndCheckCast(JsonArray<N>& expected)
|
||||
{
|
||||
value = expected;
|
||||
const Printable& actual = value;
|
||||
Assert::AreEqual((void*) &expected, (void*) &actual);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "StringBuilder.h"
|
||||
#include "JsonValue.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Generator;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(JsonValue_PrintTo_Tests)
|
||||
{
|
||||
char buffer[1024];
|
||||
size_t returnValue;
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(String)
|
||||
{
|
||||
setValueTo("hello");
|
||||
outputMustBe("\"hello\"");
|
||||
}
|
||||
|
||||
TEST_METHOD(Float)
|
||||
{
|
||||
setValueTo(3.1415f);
|
||||
outputMustBe("3.14");
|
||||
}
|
||||
|
||||
TEST_METHOD(DoubleZeroDigits)
|
||||
{
|
||||
setValueTo<0>(3.14159265358979323846);
|
||||
outputMustBe("3");
|
||||
}
|
||||
|
||||
TEST_METHOD(DoubleOneDigit)
|
||||
{
|
||||
setValueTo<1>(3.14159265358979323846);
|
||||
outputMustBe("3.1");
|
||||
}
|
||||
|
||||
TEST_METHOD(DoubleTwoDigits)
|
||||
{
|
||||
setValueTo<2>(3.14159265358979323846);
|
||||
outputMustBe("3.14");
|
||||
}
|
||||
|
||||
TEST_METHOD(Integer)
|
||||
{
|
||||
setValueTo(314);
|
||||
outputMustBe("314");
|
||||
}
|
||||
|
||||
TEST_METHOD(Char)
|
||||
{
|
||||
setValueTo('A');
|
||||
outputMustBe("65");
|
||||
}
|
||||
|
||||
TEST_METHOD(Short)
|
||||
{
|
||||
setValueTo((short)314);
|
||||
outputMustBe("314");
|
||||
}
|
||||
|
||||
TEST_METHOD(Long)
|
||||
{
|
||||
setValueTo(314159265L);
|
||||
outputMustBe("314159265");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<int DIGITS>
|
||||
void setValueTo(double value)
|
||||
{
|
||||
StringBuilder sb(buffer, sizeof(buffer));
|
||||
JsonValue jsonValue;
|
||||
jsonValue.set<DIGITS>(value);
|
||||
returnValue = jsonValue.printTo(sb);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void setValueTo(T value)
|
||||
{
|
||||
StringBuilder sb(buffer, sizeof(buffer));
|
||||
JsonValue jsonValue;
|
||||
jsonValue = value;
|
||||
returnValue = jsonValue.printTo(sb);
|
||||
}
|
||||
|
||||
void outputMustBe(const char* expected)
|
||||
{
|
||||
Assert::AreEqual(expected, buffer);
|
||||
Assert::AreEqual(strlen(expected), returnValue);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "StringBuilder.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
namespace JsonGeneratorTests
|
||||
{
|
||||
TEST_CLASS(StringBuilderTests)
|
||||
{
|
||||
char buffer[20];
|
||||
Print* sb;
|
||||
size_t returnValue;
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD_INITIALIZE(Initialize)
|
||||
{
|
||||
sb = new StringBuilder(buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
TEST_METHOD(InitialState)
|
||||
{
|
||||
outputMustBe("");
|
||||
}
|
||||
|
||||
TEST_METHOD(OverCapacity)
|
||||
{
|
||||
print("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
resultMustBe(19);
|
||||
|
||||
print("ABC");
|
||||
resultMustBe(0);
|
||||
|
||||
outputMustBe("ABCDEFGHIJKLMNOPQRS");
|
||||
}
|
||||
|
||||
TEST_METHOD(EmptyString)
|
||||
{
|
||||
print("");
|
||||
resultMustBe(0);
|
||||
outputMustBe("");
|
||||
}
|
||||
|
||||
TEST_METHOD(OneString)
|
||||
{
|
||||
print("ABCD");
|
||||
resultMustBe(4);
|
||||
outputMustBe("ABCD");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoStrings)
|
||||
{
|
||||
print("ABCD");
|
||||
resultMustBe(4);
|
||||
|
||||
print("EFGH");
|
||||
resultMustBe(4);
|
||||
|
||||
outputMustBe("ABCDEFGH");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void print(const char* value)
|
||||
{
|
||||
returnValue = sb->print(value);
|
||||
}
|
||||
|
||||
void outputMustBe(const char* expected)
|
||||
{
|
||||
Assert::AreEqual(expected, buffer);
|
||||
}
|
||||
|
||||
void resultMustBe(size_t expected)
|
||||
{
|
||||
Assert::AreEqual(expected, returnValue);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
// This file is here to help the Arduino IDE find the .cpp files
|
||||
|
||||
#include "JsonParser/JsonArray.cpp"
|
||||
#include "JsonParser/JsonObject.cpp"
|
||||
#include "JsonParser/JsonParserBase.cpp"
|
||||
#include "JsonParser/JsonValue.cpp"
|
||||
#include "JsonParser/JsonToken.cpp"
|
||||
#include "JsonParser/jsmn.cpp"
|
@ -1,6 +0,0 @@
|
||||
/*
|
||||
* malloc-free JSON parser for Arduino
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonParser/JsonParser.h"
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
DEPRECATED JsonObject JsonArray::getHashTable(int index)
|
||||
{
|
||||
return operator[](index);
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonValue.h"
|
||||
#include "JsonArrayIterator.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
class JsonObject;
|
||||
|
||||
// A JSON array
|
||||
class JsonArray : JsonValue
|
||||
{
|
||||
public:
|
||||
|
||||
// Create an invalid array
|
||||
JsonArray()
|
||||
{
|
||||
}
|
||||
|
||||
// Convert a JsonValue into a JsonArray
|
||||
JsonArray(JsonValue value)
|
||||
: JsonValue(value)
|
||||
{
|
||||
}
|
||||
|
||||
// Tell if the array is valid
|
||||
bool success()
|
||||
{
|
||||
return isArray();
|
||||
}
|
||||
|
||||
// Get the JsonValue at specified index
|
||||
JsonValue operator[](int index)
|
||||
{
|
||||
return JsonValue::operator[](index);
|
||||
}
|
||||
|
||||
// Get the size of the array
|
||||
int size()
|
||||
{
|
||||
return isArray() ? childrenCount() : 0;
|
||||
}
|
||||
|
||||
// Get an iterator pointing to the beginning of the array
|
||||
JsonArrayIterator begin()
|
||||
{
|
||||
return isArray() ? firstChild() : null();
|
||||
}
|
||||
|
||||
// Gets an iterator pointing to the end of the array
|
||||
JsonArrayIterator end()
|
||||
{
|
||||
return isArray() ? nextSibling() : null();
|
||||
}
|
||||
|
||||
// Obsolete: Use size() instead
|
||||
DEPRECATED int getLength()
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED JsonArray getArray(int index)
|
||||
{
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED bool getBool(int index)
|
||||
{
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED double getDouble(int index)
|
||||
{
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED JsonObject getHashTable(int index);
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED long getLong(int index)
|
||||
{
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED char* getString(int index)
|
||||
{
|
||||
return operator[](index);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonValue.h"
|
||||
#include "JsonToken.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
// An iterator for JsonArray
|
||||
class JsonArrayIterator : JsonToken
|
||||
{
|
||||
public:
|
||||
|
||||
// Create an iterator pointing at the specified JsonToken
|
||||
JsonArrayIterator(JsonToken token)
|
||||
: JsonToken(token)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Move iterator forward
|
||||
void operator++()
|
||||
{
|
||||
*this = JsonArrayIterator(nextSibling());
|
||||
}
|
||||
|
||||
// Get the value pointed by the iterator
|
||||
JsonValue operator*() const
|
||||
{
|
||||
return JsonValue(*this);
|
||||
}
|
||||
|
||||
// Test iterator equality
|
||||
bool operator!= (const JsonArrayIterator& other) const
|
||||
{
|
||||
return JsonToken::operator!=(other);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
#include "JsonValue.h"
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
DEPRECATED JsonArray JsonObject::getArray(const char* key)
|
||||
{
|
||||
return operator[](key);
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonValue.h"
|
||||
#include "JsonObjectIterator.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
class JsonArray;
|
||||
|
||||
// A JSON Object (ie hash-table/dictionary)
|
||||
class JsonObject : JsonValue
|
||||
{
|
||||
public:
|
||||
|
||||
// Create an invalid JsonObject
|
||||
JsonObject()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Convert a JsonValue into a JsonObject
|
||||
JsonObject(JsonValue value)
|
||||
: JsonValue(value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Tell if the object is valid
|
||||
bool success()
|
||||
{
|
||||
return isObject();
|
||||
}
|
||||
|
||||
// Get the value associated with the specified key.
|
||||
JsonValue operator[](const char* key)
|
||||
{
|
||||
return JsonValue::operator[](key);
|
||||
}
|
||||
|
||||
// Tell if the specified key exists in the object.
|
||||
bool containsKey(const char* key)
|
||||
{
|
||||
return operator[](key).success();
|
||||
}
|
||||
|
||||
// Get an iterator pointing at the beginning of the object
|
||||
JsonObjectIterator begin()
|
||||
{
|
||||
return isObject() ? firstChild() : null();
|
||||
}
|
||||
|
||||
// Get an iterator pointing at the end of the object
|
||||
JsonObjectIterator end()
|
||||
{
|
||||
return isObject() ? nextSibling() : null();
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED JsonArray getArray(const char* key);
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED bool getBool(const char* key)
|
||||
{
|
||||
return operator[](key);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED double getDouble(const char* key)
|
||||
{
|
||||
return operator[](key);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED JsonObject getHashTable(const char* key)
|
||||
{
|
||||
return operator[](key);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED long getLong(const char* key)
|
||||
{
|
||||
return operator[](key);
|
||||
}
|
||||
|
||||
// Obsolete: Use operator[] instead
|
||||
DEPRECATED char* getString(const char* key)
|
||||
{
|
||||
return operator[](key);
|
||||
}
|
||||
};
|
||||
|
||||
// Obsolete: Use JsonObject instead
|
||||
DEPRECATED typedef JsonObject JsonHashTable;
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonValue.h"
|
||||
#include "JsonPair.h"
|
||||
#include "JsonToken.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
// An iterator for JsonObject
|
||||
class JsonObjectIterator : JsonToken
|
||||
{
|
||||
public:
|
||||
|
||||
// Create an iterator pointing at the specified token
|
||||
JsonObjectIterator(JsonToken token)
|
||||
: JsonToken(token)
|
||||
{
|
||||
}
|
||||
|
||||
// Move to the next JsonPair
|
||||
void operator++()
|
||||
{
|
||||
*this = JsonObjectIterator(nextSibling().nextSibling());
|
||||
}
|
||||
|
||||
// Get the JsonPair pointed by the iterator
|
||||
JsonPair operator*() const
|
||||
{
|
||||
return JsonPair(*this);
|
||||
}
|
||||
|
||||
// Test iterator equality
|
||||
bool operator!= (const JsonObjectIterator& other) const
|
||||
{
|
||||
return JsonToken::operator!=(other);
|
||||
}
|
||||
|
||||
// Get the key of the JsonPair pointed by the iterator
|
||||
const char* key() const
|
||||
{
|
||||
return operator*().key();
|
||||
}
|
||||
|
||||
// Get the key of the JsonPair pointed by the iterator
|
||||
JsonValue value() const
|
||||
{
|
||||
return operator*().value();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonValue.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
// A JSON key-value pair, as a part of a JSON object
|
||||
class JsonPair : JsonToken
|
||||
{
|
||||
public:
|
||||
// Convert a JsonToken to a JsonPair
|
||||
JsonPair(JsonToken token)
|
||||
: JsonToken(token)
|
||||
{
|
||||
}
|
||||
|
||||
// Get the key
|
||||
const char* key()
|
||||
{
|
||||
return getText();
|
||||
}
|
||||
|
||||
// Get the value
|
||||
JsonValue value()
|
||||
{
|
||||
return nextSibling();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonParserBase.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
// The JSON parser.
|
||||
//
|
||||
// You need to specifiy the number of token to be allocated for that parser.
|
||||
//
|
||||
// CAUTION: JsonArray, JsonObject and JsonValue 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, JsonObject or JsonValue that have a
|
||||
// longer life that the JsonParser.
|
||||
template <int MAX_TOKENS>
|
||||
class JsonParser : public JsonParserBase
|
||||
{
|
||||
public:
|
||||
JsonParser()
|
||||
: JsonParserBase(tokens, MAX_TOKENS)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
jsmntok_t tokens[MAX_TOKENS];
|
||||
};
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C15274DE-2695-4DFE-8520-4424223FE6DA}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>JsonParser</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="jsmn.h" />
|
||||
<ClInclude Include="JsonArray.h" />
|
||||
<ClInclude Include="JsonArrayIterator.h" />
|
||||
<ClInclude Include="JsonObject.h" />
|
||||
<ClInclude Include="JsonObjectIterator.h" />
|
||||
<ClInclude Include="JsonPair.h" />
|
||||
<ClInclude Include="JsonParser.h" />
|
||||
<ClInclude Include="JsonParserBase.h" />
|
||||
<ClInclude Include="JsonToken.h" />
|
||||
<ClInclude Include="JsonValue.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="jsmn.cpp" />
|
||||
<ClCompile Include="JsonArray.cpp" />
|
||||
<ClCompile Include="JsonObject.cpp" />
|
||||
<ClCompile Include="JsonParserBase.cpp" />
|
||||
<ClCompile Include="JsonToken.cpp" />
|
||||
<ClCompile Include="JsonValue.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,69 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="JsonParserBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonToken.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonValue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="jsmn.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonArray.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonArrayIterator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonObject.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonObjectIterator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="JsonPair.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="jsmn.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonArray.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonObject.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonParserBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonToken.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonValue.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonParserBase.h"
|
||||
#include "JsonToken.h"
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
JsonValue JsonParserBase::parse(char* json)
|
||||
{
|
||||
jsmn_parser parser;
|
||||
jsmn_init(&parser);
|
||||
|
||||
if (JSMN_SUCCESS != jsmn_parse(&parser, json, tokens, maxTokens))
|
||||
return JsonToken::null();
|
||||
|
||||
return JsonToken(json, tokens);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
// Base class for the JSON parser, in case you want to provide your own buffer
|
||||
class JsonParserBase
|
||||
{
|
||||
public:
|
||||
|
||||
// Create a JSON parser using the provided buffer
|
||||
JsonParserBase(jsmntok_t* tokens, int maxTokens)
|
||||
: tokens(tokens), maxTokens(maxTokens)
|
||||
{
|
||||
}
|
||||
|
||||
// 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
|
||||
JsonValue parse(char* json);
|
||||
|
||||
// Obsolete: use parse() instead
|
||||
DEPRECATED JsonArray parseArray(char* json)
|
||||
{
|
||||
return parse(json);
|
||||
}
|
||||
|
||||
// Obsolete: use parse() instead
|
||||
DEPRECATED JsonObject parseHashTable(char* json)
|
||||
{
|
||||
return parse(json);
|
||||
}
|
||||
|
||||
private:
|
||||
jsmntok_t* tokens;
|
||||
int maxTokens;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "JsonToken.h"
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
JsonToken JsonToken::nextSibling() const
|
||||
{
|
||||
// start with current token
|
||||
jsmntok_t* t = token;
|
||||
|
||||
// count the number of token to skip
|
||||
int yetToVisit = 1;
|
||||
|
||||
// skip all nested tokens
|
||||
while (yetToVisit)
|
||||
{
|
||||
yetToVisit += t->size - 1;
|
||||
t++;
|
||||
}
|
||||
|
||||
// build a JsonToken at the new location
|
||||
return JsonToken(json, t);
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jsmn.h"
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
// A pointer to a JSON token
|
||||
class JsonToken
|
||||
{
|
||||
public:
|
||||
|
||||
// Create a "null" pointer
|
||||
JsonToken()
|
||||
: token(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Create a pointer to the specified JSON token
|
||||
JsonToken(char* json, jsmntok_t* token)
|
||||
: json(json), token(token)
|
||||
{
|
||||
}
|
||||
|
||||
// Get content of the JSON token
|
||||
char* getText()
|
||||
{
|
||||
json[token->end] = 0;
|
||||
return json + token->start;
|
||||
}
|
||||
|
||||
// Get the number of children tokens
|
||||
int childrenCount()
|
||||
{
|
||||
return token->size;
|
||||
}
|
||||
|
||||
// Get a pointer to the first child of the current token
|
||||
JsonToken firstChild() const
|
||||
{
|
||||
return JsonToken(json, token + 1);
|
||||
}
|
||||
|
||||
// Get a pointer to the next sibling token (ie skiping the children tokens)
|
||||
JsonToken nextSibling() const;
|
||||
|
||||
// Test equality
|
||||
bool operator!=(const JsonToken& other) const
|
||||
{
|
||||
return token != other.token;
|
||||
}
|
||||
|
||||
// Tell if the pointer is "null"
|
||||
bool isValid()
|
||||
{
|
||||
return token != 0;
|
||||
}
|
||||
|
||||
// Tell if the JSON token is a JSON object
|
||||
bool isObject()
|
||||
{
|
||||
return token != 0 && token->type == JSMN_OBJECT;
|
||||
}
|
||||
|
||||
// Tell if the JSON token is a JSON array
|
||||
bool isArray()
|
||||
{
|
||||
return token != 0 && token->type == JSMN_ARRAY;
|
||||
}
|
||||
|
||||
// Tell if the JSON token is a primitive
|
||||
bool isPrimitive()
|
||||
{
|
||||
return token != 0 && token->type == JSMN_PRIMITIVE;
|
||||
}
|
||||
|
||||
// Tell if the JSON token is a string
|
||||
bool isString()
|
||||
{
|
||||
return token != 0 && token->type == JSMN_STRING;
|
||||
}
|
||||
|
||||
// Explicit wait to create a "null" JsonToken
|
||||
static JsonToken null()
|
||||
{
|
||||
return JsonToken();
|
||||
}
|
||||
|
||||
private:
|
||||
char* json;
|
||||
jsmntok_t* token;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // for strtol, strtod
|
||||
#include <string.h> // for strcmp()
|
||||
#include "JsonArray.h"
|
||||
#include "JsonObject.h"
|
||||
#include "JsonValue.h"
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
// Convert the JsonValue to a bool.
|
||||
// Returns false if the JsonValue is not a primitve.
|
||||
JsonValue::operator bool()
|
||||
{
|
||||
if (!isPrimitive()) return 0;
|
||||
|
||||
char *text = getText();
|
||||
|
||||
// "true"
|
||||
if (text[0] == 't') return true;
|
||||
|
||||
// "false"
|
||||
if (text[0] == 'f') return false;
|
||||
|
||||
// "null"
|
||||
if (text[0] == 'n') return false;
|
||||
|
||||
// number
|
||||
return strtol(text, 0, 0) != 0;
|
||||
}
|
||||
|
||||
// Convert the JsonValue to a floating point value.
|
||||
// Returns false if the JsonValue is not a number.
|
||||
JsonValue::operator double()
|
||||
{
|
||||
return isPrimitive() ? strtod(getText(), 0) : 0;
|
||||
}
|
||||
|
||||
// Convert the JsonValue to a floating point value.
|
||||
// Returns false if the JsonValue is not a number.
|
||||
JsonValue::operator long()
|
||||
{
|
||||
return isPrimitive() ? strtol(getText(), 0, 0) : 0;
|
||||
}
|
||||
|
||||
// Convert the JsonValue to a string.
|
||||
// Returns 0 if the JsonValue is not a string.
|
||||
JsonValue::operator char*()
|
||||
{
|
||||
return isString() || isPrimitive() ? getText() : 0;
|
||||
}
|
||||
|
||||
// Get the nested value at the specified index.
|
||||
// Returns an invalid JsonValue if the current value is not an array.
|
||||
JsonValue JsonValue::operator[](int index)
|
||||
{
|
||||
// sanity check
|
||||
if (index < 0 || !isArray() || index >= childrenCount())
|
||||
return null();
|
||||
|
||||
// skip first token, it's the whole object
|
||||
JsonToken runningToken = firstChild();
|
||||
|
||||
// skip all tokens before the specified index
|
||||
for (int i = 0; i < index; i++)
|
||||
{
|
||||
// move forward: current + nested tokens
|
||||
runningToken = runningToken.nextSibling();
|
||||
}
|
||||
|
||||
return runningToken;
|
||||
}
|
||||
|
||||
// Get the nested value matching the specified index.
|
||||
// Returns an invalid JsonValue if the current value is not an object.
|
||||
JsonValue JsonValue::operator[](const char* desiredKey)
|
||||
{
|
||||
// sanity check
|
||||
if (desiredKey == 0 || !isObject())
|
||||
return null();
|
||||
|
||||
// skip first token, it's the whole object
|
||||
JsonToken runningToken = firstChild();
|
||||
|
||||
// scan each keys
|
||||
for (int i = 0; i < childrenCount() / 2; i++)
|
||||
{
|
||||
// get 'key' token string
|
||||
char* key = runningToken.getText();
|
||||
|
||||
// move to the 'value' token
|
||||
runningToken = runningToken.nextSibling();
|
||||
|
||||
// compare with desired name
|
||||
if (strcmp(desiredKey, key) == 0)
|
||||
{
|
||||
// return the value token that follows the key token
|
||||
return runningToken;
|
||||
}
|
||||
|
||||
// skip nested tokens
|
||||
runningToken = runningToken.nextSibling();
|
||||
}
|
||||
|
||||
// nothing found, return NULL
|
||||
return null();
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonToken.h"
|
||||
|
||||
#ifndef ARDUINO_JSON_NO_DEPRECATION_WARNING
|
||||
#ifdef __GNUC__
|
||||
#define DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEPRECATED __declspec(deprecated)
|
||||
#endif
|
||||
#else
|
||||
#define DEPRECATED
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
// A JSON value
|
||||
// Can be converted to string, double, bool, array or object.
|
||||
class JsonValue : protected JsonToken
|
||||
{
|
||||
public:
|
||||
|
||||
// Create a invalid value
|
||||
JsonValue()
|
||||
{
|
||||
}
|
||||
|
||||
// Convert a JsonToken to a JsonValue
|
||||
JsonValue(JsonToken token)
|
||||
: JsonToken(token)
|
||||
{
|
||||
}
|
||||
|
||||
// Tell is the JsonValue is valid
|
||||
bool success()
|
||||
{
|
||||
return isValid();
|
||||
}
|
||||
|
||||
// Convert the JsonValue to a bool.
|
||||
// Returns false if the JsonValue is not a primitve.
|
||||
operator bool();
|
||||
|
||||
// Convert the JsonValue to a floating point value.
|
||||
// Returns false if the JsonValue is not a number.
|
||||
operator double();
|
||||
|
||||
// Convert the JsonValue to a long integer.
|
||||
// Returns 0 if the JsonValue is not a number.
|
||||
operator long();
|
||||
|
||||
// Convert the JsonValue to a string.
|
||||
// Returns 0 if the JsonValue is not a string.
|
||||
operator char*();
|
||||
|
||||
// Get the nested value at the specified index.
|
||||
// Returns an invalid JsonValue if the current value is not an array.
|
||||
JsonValue operator[](int index);
|
||||
|
||||
// Get the nested value matching the specified index.
|
||||
// Returns an invalid JsonValue if the current value is not an object.
|
||||
JsonValue operator[](const char* key);
|
||||
};
|
||||
}
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
Arduino JSON library - Parser
|
||||
=============================
|
||||
|
||||
This library is an thin C++ wrapper around the *jsmn* tokenizer: http://zserge.com/jsmn.html
|
||||
|
||||
It's design to be very lightweight, works without any allocation on the heap (no malloc) and supports nested objects.
|
||||
|
||||
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
|
||||
* Elegant API, very easy to use
|
||||
* Fixed memory allocation (no malloc)
|
||||
* Small footprint
|
||||
* MIT License
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
JsonParser<32> parser;
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
JsonObject root = parser.parse(json);
|
||||
|
||||
char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
|
||||
How to use ?
|
||||
-------------
|
||||
|
||||
### 1. Install the library
|
||||
|
||||
Download the library and extract it to:
|
||||
|
||||
<your Arduino Sketch folder>/libraries/ArduinoJson
|
||||
|
||||
### 2. Import in your sketch
|
||||
|
||||
Just add the following lines at the top of your `.ino` file:
|
||||
|
||||
#include <JsonParser.h>
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
> ##### Having a namespace conflict?
|
||||
> To be able to use both `ArduinoJson::Generator` and `ArduinoJson::Parser` in the same file, you need to do one of the followings:
|
||||
>
|
||||
> * Put the `using` statements into different functions
|
||||
> * `using namespace ArduinoJson`, then prefix the type names by `Generator::` or `Parser::`
|
||||
> * Create aliases for the namespaces or the types (C++11 only)
|
||||
|
||||
### 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 object 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 an object (like `{"key":"value"}`) or an array (like `[1,2]`).
|
||||
|
||||
The nested objects can be either arrays, booleans, objects, numbers or strings.
|
||||
If you need other type, you can get the string value and parse it yourself.
|
||||
|
||||
#### Object
|
||||
|
||||
Consider we have a `char json[]` containing to the following JSON string:
|
||||
|
||||
{
|
||||
"sensor":"gps",
|
||||
"time":1351824120,
|
||||
"data":[48.756080,2.302038]
|
||||
}
|
||||
|
||||
In this case the string contains a JSON object, so you need to extract a `JsonObject`:
|
||||
|
||||
JsonObject root = parser.parse(json);
|
||||
|
||||
To check if the parsing was successful, you must check:
|
||||
|
||||
if (!root.success())
|
||||
{
|
||||
// Parsing fail: could be an invalid JSON, or too many tokens
|
||||
}
|
||||
|
||||
And then extract the member you need:
|
||||
|
||||
char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
You can also iterate through the key-value pairs of the object:
|
||||
|
||||
for (JsonObjectIterator i=root.begin(); i!=root.end(); ++i)
|
||||
{
|
||||
Serial.println(i.key());
|
||||
Serial.println((char*)i.value());
|
||||
}
|
||||
|
||||
#### Array
|
||||
|
||||
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`:
|
||||
|
||||
JsonArray root = parser.parse(json);
|
||||
|
||||
To check if the parsing was successful, you must check:
|
||||
|
||||
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:
|
||||
|
||||
double a = root[0][0];
|
||||
double b = root[0][1];
|
||||
double c = root[1][0];
|
||||
double d = root[1][1];
|
||||
|
||||
You can also iterate through the key-value pairs of the object:
|
||||
|
||||
for (JsonArrayIterator i=array.begin(); i!=array.end(); ++i)
|
||||
{
|
||||
Serial.println((char*)*i);
|
||||
}
|
||||
|
||||
Common pitfalls
|
||||
---------------
|
||||
|
||||
### 1. Not enough tokens
|
||||
|
||||
By design, the library has no way to tell you why `JsonParser::parse()` 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, `JsonValue`, `JsonArray` and `JsonObject` 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::parse()`, 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
|
||||
------------
|
||||
|
||||
Here are the size of the main classes of the library.
|
||||
|
||||
This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor.
|
||||
|
||||
| Type | Size in bytes |
|
||||
| ------------ | ------------- |
|
||||
| `Parser<N>` | 4 + 8 x N |
|
||||
| `JsonArray` | 4 |
|
||||
| `JsonObject` | 4 |
|
||||
| `JsonValue` | 4 |
|
||||
|
||||
Code size
|
||||
---------
|
||||
|
||||
The sizes have been obtained with Arduino IDE 1.0.5 for a Duemilanove.
|
||||
|
||||
### Minimum setup
|
||||
|
||||
| Function | Size |
|
||||
| ------------------------------------ | ---- |
|
||||
| `jsmn_parse()` | 962 |
|
||||
| `JsonValue::operator[](char const*)` | 218 |
|
||||
| `JsonParserBase::parse()` | 116 |
|
||||
| `JsonValue::operator[](int)` | 108 |
|
||||
| `strcmp()` | 18 |
|
||||
|
||||
### Additional space for integers
|
||||
|
||||
| Function | Size |
|
||||
| ---------------------------- | ---- |
|
||||
| `strtol()` | 606 |
|
||||
| `JsonValue::operator long()` | 94 |
|
||||
|
||||
### Additional space for floating points
|
||||
|
||||
| Function | Size |
|
||||
| -------------------------------- | ----- |
|
||||
| `strtod()` | 1369 |
|
||||
| `JsonValue::operator double()` | 82 |
|
@ -1,255 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jsmn.h"
|
||||
|
||||
/**
|
||||
* Allocates a fresh unused token from the token pull.
|
||||
*/
|
||||
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
|
||||
jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *tok;
|
||||
if (parser->toknext >= num_tokens) {
|
||||
return NULL;
|
||||
}
|
||||
tok = &tokens[parser->toknext++];
|
||||
tok->start = tok->end = -1;
|
||||
tok->size = 0;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
tok->parent = -1;
|
||||
#endif
|
||||
return tok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills token type and boundaries.
|
||||
*/
|
||||
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
|
||||
int start, int end) {
|
||||
token->type = type;
|
||||
token->start = start;
|
||||
token->end = end;
|
||||
token->size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills next available token with JSON primitive.
|
||||
*/
|
||||
static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
|
||||
jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
int start;
|
||||
|
||||
start = parser->pos;
|
||||
|
||||
for (; js[parser->pos] != '\0'; parser->pos++) {
|
||||
switch (js[parser->pos]) {
|
||||
#ifndef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by "," or "}" or "]" */
|
||||
case ':':
|
||||
#endif
|
||||
case '\t' : case '\r' : case '\n' : case ' ' :
|
||||
case ',' : case ']' : case '}' :
|
||||
goto found;
|
||||
}
|
||||
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitive must be followed by a comma/object/array */
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
#endif
|
||||
|
||||
found:
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
parser->pos--;
|
||||
return JSMN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filsl next token with JSON string.
|
||||
*/
|
||||
static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
|
||||
jsmntok_t *tokens, size_t num_tokens) {
|
||||
jsmntok_t *token;
|
||||
|
||||
int start = parser->pos;
|
||||
|
||||
parser->pos++;
|
||||
|
||||
/* Skip starting quote */
|
||||
for (; js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c = js[parser->pos];
|
||||
|
||||
/* Quote: end of string */
|
||||
if (c == '\"') {
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL) {
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_NOMEM;
|
||||
}
|
||||
jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
return JSMN_SUCCESS;
|
||||
}
|
||||
|
||||
/* Backslash: Quoted symbol expected */
|
||||
if (c == '\\') {
|
||||
parser->pos++;
|
||||
switch (js[parser->pos]) {
|
||||
/* Allowed escaped symbols */
|
||||
case '\"': case '/' : case '\\' : case 'b' :
|
||||
case 'f' : case 'r' : case 'n' : case 't' :
|
||||
break;
|
||||
/* Allows escaped symbol \uXXXX */
|
||||
case 'u':
|
||||
/* TODO */
|
||||
break;
|
||||
/* Unexpected symbol */
|
||||
default:
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
parser->pos = start;
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse JSON string and fill tokens.
|
||||
*/
|
||||
jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens,
|
||||
unsigned int num_tokens) {
|
||||
jsmnerr_t r;
|
||||
int i;
|
||||
jsmntok_t *token;
|
||||
|
||||
for (; js[parser->pos] != '\0'; parser->pos++) {
|
||||
char c;
|
||||
jsmntype_t type;
|
||||
|
||||
c = js[parser->pos];
|
||||
switch (c) {
|
||||
case '{': case '[':
|
||||
token = jsmn_alloc_token(parser, tokens, num_tokens);
|
||||
if (token == NULL)
|
||||
return JSMN_ERROR_NOMEM;
|
||||
if (parser->toksuper != -1) {
|
||||
tokens[parser->toksuper].size++;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
token->parent = parser->toksuper;
|
||||
#endif
|
||||
}
|
||||
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
token->start = parser->pos;
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case '}': case ']':
|
||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
if (parser->toknext < 1) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token = &tokens[parser->toknext - 1];
|
||||
for (;;) {
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
token->end = parser->pos + 1;
|
||||
parser->toksuper = token->parent;
|
||||
break;
|
||||
}
|
||||
if (token->parent == -1) {
|
||||
break;
|
||||
}
|
||||
token = &tokens[token->parent];
|
||||
}
|
||||
#else
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
if (token->type != type) {
|
||||
return JSMN_ERROR_INVAL;
|
||||
}
|
||||
parser->toksuper = -1;
|
||||
token->end = parser->pos + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error if unmatched closing bracket */
|
||||
if (i == -1) return JSMN_ERROR_INVAL;
|
||||
for (; i >= 0; i--) {
|
||||
token = &tokens[i];
|
||||
if (token->start != -1 && token->end == -1) {
|
||||
parser->toksuper = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case '\"':
|
||||
r = jsmn_parse_string(parser, js, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
if (parser->toksuper != -1)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
|
||||
break;
|
||||
#ifdef JSMN_STRICT
|
||||
/* In strict mode primitives are: numbers and booleans */
|
||||
case '-': case '0': case '1' : case '2': case '3' : case '4':
|
||||
case '5': case '6': case '7' : case '8': case '9':
|
||||
case 't': case 'f': case 'n' :
|
||||
#else
|
||||
/* In non-strict mode every unquoted value is a primitive */
|
||||
default:
|
||||
#endif
|
||||
r = jsmn_parse_primitive(parser, js, tokens, num_tokens);
|
||||
if (r < 0) return r;
|
||||
if (parser->toksuper != -1)
|
||||
tokens[parser->toksuper].size++;
|
||||
break;
|
||||
|
||||
#ifdef JSMN_STRICT
|
||||
/* Unexpected char in strict mode */
|
||||
default:
|
||||
return JSMN_ERROR_INVAL;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (i = parser->toknext - 1; i >= 0; i--) {
|
||||
/* Unmatched opened object or array */
|
||||
if (tokens[i].start != -1 && tokens[i].end == -1) {
|
||||
return JSMN_ERROR_PART;
|
||||
}
|
||||
}
|
||||
|
||||
return JSMN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new parser based over a given buffer with an array of tokens
|
||||
* available.
|
||||
*/
|
||||
void jsmn_init(jsmn_parser *parser) {
|
||||
parser->pos = 0;
|
||||
parser->toknext = 0;
|
||||
parser->toksuper = -1;
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
#ifndef __JSMN_H_
|
||||
#define __JSMN_H_
|
||||
|
||||
/**
|
||||
* JSON type identifier. Basic types are:
|
||||
* o Object
|
||||
* o Array
|
||||
* o String
|
||||
* o Other primitive: number, boolean (true/false) or null
|
||||
*/
|
||||
typedef enum {
|
||||
JSMN_PRIMITIVE = 0,
|
||||
JSMN_OBJECT = 1,
|
||||
JSMN_ARRAY = 2,
|
||||
JSMN_STRING = 3
|
||||
} jsmntype_t;
|
||||
|
||||
typedef enum {
|
||||
/* Not enough tokens were provided */
|
||||
JSMN_ERROR_NOMEM = -1,
|
||||
/* Invalid character inside JSON string */
|
||||
JSMN_ERROR_INVAL = -2,
|
||||
/* The string is not a full JSON packet, more bytes expected */
|
||||
JSMN_ERROR_PART = -3,
|
||||
/* Everything was fine */
|
||||
JSMN_SUCCESS = 0
|
||||
} jsmnerr_t;
|
||||
|
||||
/**
|
||||
* JSON token description.
|
||||
* @param type type (object, array, string etc.)
|
||||
* @param start start position in JSON data string
|
||||
* @param end end position in JSON data string
|
||||
*/
|
||||
typedef struct {
|
||||
jsmntype_t type;
|
||||
int start;
|
||||
int end;
|
||||
int size;
|
||||
#ifdef JSMN_PARENT_LINKS
|
||||
int parent;
|
||||
#endif
|
||||
} jsmntok_t;
|
||||
|
||||
/**
|
||||
* JSON parser. Contains an array of token blocks available. Also stores
|
||||
* the string being parsed now and current position in that string
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int pos; /* offset in the JSON string */
|
||||
int toknext; /* next token to allocate */
|
||||
int toksuper; /* superior token node, e.g parent object or array */
|
||||
} jsmn_parser;
|
||||
|
||||
/**
|
||||
* Create JSON parser over an array of tokens
|
||||
*/
|
||||
void jsmn_init(jsmn_parser *parser);
|
||||
|
||||
/**
|
||||
* Run JSON parser. It parses a JSON data string into and array of tokens, each describing
|
||||
* a single JSON object.
|
||||
*/
|
||||
jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js,
|
||||
jsmntok_t *tokens, unsigned int num_tokens);
|
||||
|
||||
#endif /* __JSMN_H_ */
|
@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonParser.h"
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
namespace ArduinoJsonParserTests
|
||||
{
|
||||
TEST_CLASS(GbathreeBug)
|
||||
{
|
||||
char json[1024];
|
||||
JsonParser<200> parser;
|
||||
JsonHashTable root;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD_INITIALIZE(Initialize)
|
||||
{
|
||||
// BUG described here:
|
||||
// http://forum.arduino.cc/index.php?topic=172578.msg1608219#msg1608219
|
||||
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]}");
|
||||
root = parser.parseHashTable(json);
|
||||
}
|
||||
|
||||
TEST_METHOD(Root)
|
||||
{
|
||||
Assert::IsTrue(root.success());
|
||||
}
|
||||
|
||||
TEST_METHOD(ProtocolName)
|
||||
{
|
||||
string protocol_name = root.getString("protocol_name");
|
||||
Assert::AreEqual(string("fluorescence"), protocol_name);
|
||||
}
|
||||
|
||||
TEST_METHOD(Repeats)
|
||||
{
|
||||
Assert::AreEqual(1L, root.getLong("repeats"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Wait)
|
||||
{
|
||||
Assert::AreEqual(0L, root.getLong("wait"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Measurements)
|
||||
{
|
||||
Assert::AreEqual(3L, root.getLong("measurements"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Meas2_Light)
|
||||
{
|
||||
Assert::AreEqual(15L, root.getLong("meas2_light"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Meas1_Baseline)
|
||||
{
|
||||
Assert::AreEqual(0L, root.getLong("meas1_baseline"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Act_Light)
|
||||
{
|
||||
Assert::AreEqual(20L, root.getLong("act_light"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Pulsesize)
|
||||
{
|
||||
Assert::AreEqual(25L, root.getLong("pulsesize"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Pulsedistance)
|
||||
{
|
||||
Assert::AreEqual(10000L, root.getLong("pulsedistance"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Actintensity1)
|
||||
{
|
||||
Assert::AreEqual(50L, root.getLong("actintensity1"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Actintensity2)
|
||||
{
|
||||
Assert::AreEqual(255L, root.getLong("actintensity2"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Measintensity)
|
||||
{
|
||||
Assert::AreEqual(255L, root.getLong("measintensity"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Calintensity)
|
||||
{
|
||||
Assert::AreEqual(255L, root.getLong("calintensity"));
|
||||
}
|
||||
|
||||
TEST_METHOD(Pulses)
|
||||
{
|
||||
// "pulses":[50,50,50]
|
||||
|
||||
JsonArray array = root.getArray("pulses");
|
||||
Assert::IsTrue(array.success());
|
||||
|
||||
Assert::AreEqual(3, array.getLength());
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
Assert::AreEqual(50L, array.getLong(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(Act)
|
||||
{
|
||||
// "act":[2,1,2,2]
|
||||
|
||||
JsonArray array = root.getArray("act");
|
||||
Assert::IsTrue(array.success());
|
||||
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
Assert::AreEqual(2L, array.getLong(0));
|
||||
Assert::AreEqual(1L, array.getLong(1));
|
||||
Assert::AreEqual(2L, array.getLong(2));
|
||||
Assert::AreEqual(2L, array.getLong(3));
|
||||
}
|
||||
|
||||
TEST_METHOD(Detectors)
|
||||
{
|
||||
// "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]]
|
||||
|
||||
JsonArray array = root.getArray("detectors");
|
||||
Assert::IsTrue(array.success());
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert::AreEqual(4, array.getArray(i).getLength());
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
Assert::AreEqual(34L, array.getArray(i).getLong(j));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(Alta)
|
||||
{
|
||||
// alta:[2,2,2,2]
|
||||
|
||||
JsonArray array = root.getArray("alta");
|
||||
Assert::IsTrue(array.success());
|
||||
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert::AreEqual(2L, array.getLong(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(Altb)
|
||||
{
|
||||
// altb:[2,2,2,2]
|
||||
|
||||
JsonArray array = root.getArray("altb");
|
||||
Assert::IsTrue(array.success());
|
||||
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert::AreEqual(2L, array.getLong(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(Measlights)
|
||||
{
|
||||
// "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||
|
||||
JsonArray array = root.getArray("measlights");
|
||||
Assert::IsTrue(array.success());
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert::AreEqual(4, array.getArray(i).getLength());
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
Assert::AreEqual(15L, array.getArray(i).getLong(j));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(Measlights2)
|
||||
{
|
||||
// "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
|
||||
|
||||
JsonArray array = root.getArray("measlights2");
|
||||
Assert::IsTrue(array.success());
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert::AreEqual(4, array.getArray(i).getLength());
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
Assert::AreEqual(15L, array.getArray(i).getLong(j));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(Altc)
|
||||
{
|
||||
// altc:[2,2,2,2]
|
||||
|
||||
JsonArray array = root.getArray("altc");
|
||||
Assert::IsTrue(array.success());
|
||||
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert::AreEqual(2L, array.getLong(i));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(Altd)
|
||||
{
|
||||
// altd:[2,2,2,2]
|
||||
|
||||
JsonArray array = root.getArray("altd");
|
||||
Assert::IsTrue(array.success());
|
||||
|
||||
Assert::AreEqual(4, array.getLength());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Assert::AreEqual(2L, array.getLong(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonParser.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
namespace JsonParserTests
|
||||
{
|
||||
TEST_CLASS(JsonArrayIteratorTests)
|
||||
{
|
||||
public:
|
||||
|
||||
TEST_METHOD(EmptyJson)
|
||||
{
|
||||
char json[] = "";
|
||||
JsonParser<1> parser;
|
||||
|
||||
JsonArray a = parser.parse(json);
|
||||
|
||||
int loopCount = 0;
|
||||
|
||||
for (long i : a)
|
||||
{
|
||||
loopCount++;
|
||||
}
|
||||
|
||||
Assert::AreEqual(0, loopCount);
|
||||
}
|
||||
|
||||
TEST_METHOD(ThreeIntegers)
|
||||
{
|
||||
char json [] = "[1,2,3]";
|
||||
long expected [] = {1, 2, 3};
|
||||
JsonParser<4> parser;
|
||||
|
||||
JsonArray a = parser.parse(json);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (long i : a)
|
||||
{
|
||||
Assert::AreEqual(expected[index++], i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_METHOD(ThreeStrings)
|
||||
{
|
||||
char json[] = "[\"1\",\"2\",\"3\"]";
|
||||
char* expected[] = {"1", "2", "3"};
|
||||
JsonParser<4> parser;
|
||||
|
||||
JsonArray a = parser.parse(json);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (const char* i : a)
|
||||
{
|
||||
Assert::AreEqual(expected[index++], i);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonParser.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
namespace ArduinoJsonParserTests
|
||||
{
|
||||
TEST_CLASS(JsonArrayTests)
|
||||
{
|
||||
JsonArray array;
|
||||
char json[256];
|
||||
jsmntok_t tokens[32];
|
||||
JsonParserBase parser = JsonParserBase(tokens, 32);
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(EmptyString)
|
||||
{
|
||||
whenInputIs("");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_METHOD(TooFewClosingBrackets)
|
||||
{
|
||||
whenInputIs("[[]");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_METHOD(TooManyClosingBrackets)
|
||||
{
|
||||
whenInputIs("[]]");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_METHOD(EmptyArray)
|
||||
{
|
||||
whenInputIs("[]");
|
||||
parseMustSucceed();
|
||||
lengthMustBe(0);
|
||||
}
|
||||
|
||||
TEST_METHOD(NotEnoughTokens)
|
||||
{
|
||||
setTokenCountTo(2);
|
||||
|
||||
whenInputIs("[1,2]");
|
||||
|
||||
parseMustFail();
|
||||
itemMustNotExist(0);
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoIntegers)
|
||||
{
|
||||
setTokenCountTo(3);
|
||||
|
||||
whenInputIs("[1,2]");
|
||||
|
||||
parseMustSucceed();
|
||||
lengthMustBe(2);
|
||||
itemMustBe(0, 1L);
|
||||
itemMustBe(1, 2L);
|
||||
itemMustNotExist(2);
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoBooleans)
|
||||
{
|
||||
setTokenCountTo(3);
|
||||
|
||||
whenInputIs("[true,false]");
|
||||
|
||||
parseMustSucceed();
|
||||
lengthMustBe(2);
|
||||
itemMustBe(0, true);
|
||||
itemMustBe(1, false);
|
||||
itemMustNotExist(2);
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoStrings)
|
||||
{
|
||||
setTokenCountTo(3);
|
||||
|
||||
whenInputIs("[\"hello\",\"world\"]");
|
||||
|
||||
parseMustSucceed();
|
||||
lengthMustBe(2);
|
||||
itemMustBe(0, "hello");
|
||||
itemMustBe(1, "world");
|
||||
itemMustNotExist(2);
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoDimensionsArray)
|
||||
{
|
||||
setTokenCountTo(7);
|
||||
|
||||
whenInputIs("[[1,2],[3,4]]");
|
||||
|
||||
parseMustSucceed();
|
||||
lengthMustBe(2);
|
||||
itemMustBe(0, 0, 1L);
|
||||
itemMustBe(0, 1, 2L);
|
||||
itemMustBe(1, 0, 3L);
|
||||
itemMustBe(1, 1, 4L);
|
||||
itemMustNotExist(2);
|
||||
}
|
||||
|
||||
TEST_METHOD(ThreeDimensionsArray)
|
||||
{
|
||||
setTokenCountTo(15);
|
||||
|
||||
whenInputIs("[[[1,2],[3,4]],[[5,6],[7,8]]]");
|
||||
|
||||
parseMustSucceed();
|
||||
lengthMustBe(2);
|
||||
itemMustBe(0, 0, 0, 1L);
|
||||
itemMustBe(0, 0, 1, 2L);
|
||||
itemMustBe(0, 1, 0, 3L);
|
||||
itemMustBe(0, 1, 1, 4L);
|
||||
itemMustBe(1, 0, 0, 5L);
|
||||
itemMustBe(1, 0, 1, 6L);
|
||||
itemMustBe(1, 1, 0, 7L);
|
||||
itemMustBe(1, 1, 1, 8L);
|
||||
itemMustNotExist(2);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void setTokenCountTo(int n)
|
||||
{
|
||||
parser = JsonParserBase(tokens, n);
|
||||
}
|
||||
|
||||
void whenInputIs(const char* input)
|
||||
{
|
||||
strcpy(json, input);
|
||||
array = parser.parseArray(json);
|
||||
}
|
||||
|
||||
void parseMustFail()
|
||||
{
|
||||
Assert::IsFalse(array.success());
|
||||
lengthMustBe(0);
|
||||
}
|
||||
|
||||
void parseMustSucceed()
|
||||
{
|
||||
Assert::IsTrue(array.success());
|
||||
}
|
||||
|
||||
void lengthMustBe(int expected)
|
||||
{
|
||||
Assert::AreEqual(expected, array.getLength());
|
||||
}
|
||||
|
||||
void itemMustBe(int index, long expected)
|
||||
{
|
||||
Assert::AreEqual(expected, array.getLong(index));
|
||||
}
|
||||
|
||||
void itemMustBe(int index, bool expected)
|
||||
{
|
||||
Assert::AreEqual(expected, array.getBool(index));
|
||||
}
|
||||
|
||||
void itemMustBe(int index, const char* expected)
|
||||
{
|
||||
Assert::AreEqual(expected, array.getString(index));
|
||||
}
|
||||
|
||||
void itemMustBe(int index0, int index1, long expected)
|
||||
{
|
||||
Assert::AreEqual(expected, array.getArray(index0).getLong(index1));
|
||||
}
|
||||
|
||||
void itemMustBe(int index0, int index1, int index2, long expected)
|
||||
{
|
||||
Assert::AreEqual(expected, array.getArray(index0).getArray(index1).getLong(index2));
|
||||
}
|
||||
|
||||
void itemMustNotExist(int index)
|
||||
{
|
||||
Assert::IsFalse(array.getHashTable(index).success());
|
||||
Assert::IsFalse(array.getArray(index).success());
|
||||
Assert::IsFalse(array.getBool(index));
|
||||
Assert::AreEqual(0.0, array.getDouble(index));
|
||||
Assert::AreEqual(0L, array.getLong(index));
|
||||
Assert::IsNull(array.getString(index));
|
||||
}
|
||||
};
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonParser.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
namespace JsonParserTests
|
||||
{
|
||||
TEST_CLASS(JsonObjectIteratorTests)
|
||||
{
|
||||
public:
|
||||
|
||||
TEST_METHOD(EmptyObject)
|
||||
{
|
||||
char json [] = "{}";
|
||||
JsonParser<1> parser;
|
||||
|
||||
JsonHashTable a = parser.parse(json);
|
||||
|
||||
int loopCount = 0;
|
||||
|
||||
for (auto i : a)
|
||||
{
|
||||
loopCount++;
|
||||
}
|
||||
|
||||
Assert::AreEqual(0, loopCount);
|
||||
}
|
||||
|
||||
TEST_METHOD(EmptyJson)
|
||||
{
|
||||
char json[] = "";
|
||||
JsonParser<1> parser;
|
||||
|
||||
JsonHashTable a = parser.parse(json);
|
||||
|
||||
int loopCount = 0;
|
||||
|
||||
for (auto i : a)
|
||||
{
|
||||
loopCount++;
|
||||
}
|
||||
|
||||
Assert::AreEqual(0, loopCount);
|
||||
}
|
||||
|
||||
TEST_METHOD(ThreeStrings)
|
||||
{
|
||||
char json[] = "{\"key1\":\"value1\",\"key2\":\"value2\",\"key3\":\"value3\"}";
|
||||
char* expectedKeys[] = {"key1", "key2", "key3"};
|
||||
char* expectedValues[] = {"value1", "value2", "value3"};
|
||||
JsonParser<7> parser;
|
||||
|
||||
JsonHashTable a = parser.parse(json);
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (auto i : a)
|
||||
{
|
||||
Assert::AreEqual(expectedKeys[index], i.key());
|
||||
Assert::AreEqual(expectedValues[index], (const char*) i.value());
|
||||
index++;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Arduino JSON library
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
|
||||
#include "CppUnitTest.h"
|
||||
#include "JsonParser.h"
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace ArduinoJson::Parser;
|
||||
|
||||
namespace ArduinoJsonParserTests
|
||||
{
|
||||
TEST_CLASS(JsonHashTableTests)
|
||||
{
|
||||
JsonHashTable hashTable;
|
||||
JsonArray nestedArray;
|
||||
char json[256];
|
||||
jsmntok_t tokens[32];
|
||||
JsonParserBase parser = JsonParserBase(tokens, 32);
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(EmptyString)
|
||||
{
|
||||
whenInputIs("");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_METHOD(EmptyHashTable)
|
||||
{
|
||||
whenInputIs("{}");
|
||||
parseMustSucceed();
|
||||
}
|
||||
|
||||
TEST_METHOD(NotEnoughTokens)
|
||||
{
|
||||
setTokenCountTo(2);
|
||||
|
||||
whenInputIs("{\"key\":0}");
|
||||
|
||||
parseMustFail();
|
||||
itemMustNotExist("key");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoIntegers)
|
||||
{
|
||||
setTokenCountTo(5);
|
||||
|
||||
whenInputIs("{\"key1\":1,\"key2\":2}");
|
||||
|
||||
parseMustSucceed();
|
||||
itemMustBe("key1", 1L);
|
||||
itemMustBe("key2", 2L);
|
||||
itemMustNotExist("key3");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoBooleans)
|
||||
{
|
||||
setTokenCountTo(5);
|
||||
|
||||
whenInputIs("{\"key1\":true,\"key2\":false}");
|
||||
|
||||
parseMustSucceed();
|
||||
itemMustBe("key1", true);
|
||||
itemMustBe("key2", false);
|
||||
itemMustNotExist("key3");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoStrings)
|
||||
{
|
||||
setTokenCountTo(5);
|
||||
|
||||
whenInputIs("{\"key1\":\"hello\",\"key2\":\"world\"}");
|
||||
|
||||
parseMustSucceed();
|
||||
itemMustBe("key1", "hello");
|
||||
itemMustBe("key2", "world");
|
||||
itemMustNotExist("key3");
|
||||
}
|
||||
|
||||
TEST_METHOD(TwoNestedArrays)
|
||||
{
|
||||
setTokenCountTo(9);
|
||||
|
||||
whenInputIs("{\"key1\":[1,2],\"key2\":[3,4]}");
|
||||
parseMustSucceed();
|
||||
|
||||
itemMustBeAnArray("key1");
|
||||
arrayLengthMustBe(2);
|
||||
arrayItemMustBe(0, 1L);
|
||||
arrayItemMustBe(1, 2L);
|
||||
arrayItemMustBe(2, 0L);
|
||||
|
||||
itemMustBeAnArray("key2");
|
||||
arrayLengthMustBe(2);
|
||||
arrayItemMustBe(0, 3L);
|
||||
arrayItemMustBe(1, 4L);
|
||||
arrayItemMustBe(2, 0L);
|
||||
|
||||
itemMustNotExist("key3");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void setTokenCountTo(int n)
|
||||
{
|
||||
parser = JsonParserBase(tokens, n);
|
||||
}
|
||||
|
||||
void whenInputIs(const char* input)
|
||||
{
|
||||
strcpy(json, input);
|
||||
hashTable = parser.parseHashTable(json);
|
||||
}
|
||||
|
||||
void parseMustFail()
|
||||
{
|
||||
Assert::IsFalse(hashTable.success());
|
||||
}
|
||||
|
||||
void parseMustSucceed()
|
||||
{
|
||||
Assert::IsTrue(hashTable.success());
|
||||
}
|
||||
|
||||
void itemMustBe(const char* key, long expected)
|
||||
{
|
||||
Assert::AreEqual(expected, hashTable.getLong(key));
|
||||
}
|
||||
|
||||
void itemMustBe(const char* key, bool expected)
|
||||
{
|
||||
Assert::AreEqual(expected, hashTable.getBool(key));
|
||||
}
|
||||
|
||||
void itemMustBe(const char* key, const char* expected)
|
||||
{
|
||||
Assert::AreEqual(expected, hashTable.getString(key));
|
||||
}
|
||||
|
||||
void itemMustNotExist(const char* key)
|
||||
{
|
||||
Assert::IsFalse(hashTable.containsKey(key));
|
||||
Assert::IsFalse(hashTable.getHashTable(key).success());
|
||||
Assert::IsFalse(hashTable.getArray(key).success());
|
||||
Assert::IsFalse(hashTable.getBool(key));
|
||||
Assert::AreEqual(0.0, hashTable.getDouble(key));
|
||||
Assert::AreEqual(0L, hashTable.getLong(key));
|
||||
Assert::IsNull(hashTable.getString(key));
|
||||
}
|
||||
|
||||
void itemMustBeAnArray(const char* key)
|
||||
{
|
||||
nestedArray = hashTable.getArray(key);
|
||||
Assert::IsTrue(nestedArray.success());
|
||||
}
|
||||
|
||||
void arrayLengthMustBe(int expected)
|
||||
{
|
||||
Assert::AreEqual(expected, nestedArray.getLength());
|
||||
}
|
||||
|
||||
void arrayItemMustBe(int index, long expected)
|
||||
{
|
||||
Assert::AreEqual(expected, nestedArray.getLong(index));
|
||||
}
|
||||
};
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4DD596EF-0185-4AB4-A3C2-F20C496F7806}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ArduinoJsonParserTests</RootNamespace>
|
||||
<ProjectName>JsonParserTests</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(VC_IncludePath);..</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ARDUINO_JSON_NO_DEPRECATION_WARNING;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="JsonObjectIteratorTests.cpp" />
|
||||
<ClCompile Include="JsonArrayTests.cpp" />
|
||||
<ClCompile Include="JsonArrayIteratorTests.cpp" />
|
||||
<ClCompile Include="JsonObjectTests.cpp" />
|
||||
<ClCompile Include="GbathreeBug.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\JsonParser\JsonParser.vcxproj">
|
||||
<Project>{c15274de-2695-4dfe-8520-4424223fe6da}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="JsonArrayTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GbathreeBug.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonObjectTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonArrayIteratorTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="JsonObjectIteratorTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,25 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
#include "CppUnitTest.h"
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace ArduinoJsonParserTests
|
||||
{
|
||||
TEST_CLASS(TestHashGenerator)
|
||||
{
|
||||
public:
|
||||
|
||||
TEST_METHOD(TestMethod1)
|
||||
{
|
||||
JsonArray<5> arr;
|
||||
arr.Add(1);
|
||||
arr.Add("Hi!");
|
||||
|
||||
JsonHashTable<4> hash;
|
||||
hash.Add("key1", 1);
|
||||
hash.Add("key2", "Hello!");
|
||||
hash.Add("key3", arr);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
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.
|
65
README.md
65
README.md
@ -1,6 +1,8 @@
|
||||
Arduino JSON library
|
||||
====================
|
||||
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
It's design to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
|
||||
@ -10,37 +12,54 @@ It has been written with Arduino in mind, but it isn't linked to Arduino librari
|
||||
Features
|
||||
--------
|
||||
|
||||
* JSON decoding: [more details here](/JsonParser/)
|
||||
* JSON encoding: [more details here](/JsonGenerator/)
|
||||
* JSON decoding
|
||||
* JSON encoding (with optional indentation)
|
||||
* Elegant API, very easy to use
|
||||
* Fixed memory allocation (no malloc)
|
||||
* Small footprint
|
||||
* MIT License
|
||||
|
||||
Feature comparison
|
||||
------------------
|
||||
Quick start
|
||||
-----------
|
||||
|
||||
| Library | Memory allocation | Nested objects | Parser size | Encoder size |
|
||||
| ------------ | ----------------- | -------------- | ----------- | ------------- |
|
||||
| Arduino JSON | static | yes | 2642 Bytes | 862 bytes |
|
||||
| json-arduino | dynamic | no | 3348 (+27%) | not supported |
|
||||
| aJson | dynamic | yes | 5088 (+93%) | 4678 (+540%) |
|
||||
#### Decoding / Parsing
|
||||
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
"Parser size" was measured with a program parsing `{"sensor":"outdoor","value":25.6}`.
|
||||
For each library, I wrote a program that extracts a string and a float. I subtracted the size of a program doing the same without any JSON parsing involved. [Source files are here](https://gist.github.com/bblanchon/e8ba914a7109f3642c0f).
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
"Encoder size" was measured with a program generating `{"sensor":"outdoor","value":25.6}`.
|
||||
[Source files are here](https://gist.github.com/bblanchon/60224e9dcfeab4ddc7e9).
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
In each case the target platform was an Arduino Duemilanove and Arduino IDE 1.0.5 was used.
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
Links: [json-arduino](https://github.com/not404/json-arduino), [aJson](https://github.com/interactive-matter/aJson)
|
||||
[See complete guide](/doc/Decoding JSON.md)
|
||||
|
||||
#### Encoding / Generating
|
||||
|
||||
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]}
|
||||
|
||||
[See complete guide](/doc/Encoding JSON.md)
|
||||
|
||||
Testimonials
|
||||
------------
|
||||
|
||||
From Arduino's Forum user `jflaplante`:
|
||||
> I tried the [aJson and json-arduino] before trying your library. I always ran into memory problem after a while.
|
||||
> 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.
|
||||
|
||||
From Arduino's Forum user `gbathree`:
|
||||
@ -49,10 +68,12 @@ From Arduino's Forum user `gbathree`:
|
||||
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.
|
||||
|
||||
Related blog posts
|
||||
-----
|
||||
From GitHub user `zacsketches`:
|
||||
|
||||
* [The project I originally wrote this library for](http://blog.benoitblanchon.fr/rfid-payment-terminal/)
|
||||
* [Motivation for this library](http://blog.benoitblanchon.fr/arduino-json-parser/)
|
||||
* [Release of version 2](http://blog.benoitblanchon.fr/arduino-json-v2-0/)
|
||||
* [Release of version 3](http://blog.benoitblanchon.fr/arduino-json-v3-0/)
|
||||
> 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!!
|
||||
|
||||
---
|
||||
|
||||
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
|
||||
}
|
@ -1,29 +1,42 @@
|
||||
/*
|
||||
* Arduino JSON library - Generator example
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <JsonGenerator.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
using namespace ArduinoJson::Generator;
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonArray<2> array;
|
||||
array.add<6>(48.756080); // 6 is the number of decimals to print
|
||||
array.add<6>(2.302038); // if not specified, 2 digits are printed
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonObject<3> root;
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
root["data"] = array;
|
||||
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
|
||||
|
||||
Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
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()
|
||||
{
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
@ -1,40 +1,37 @@
|
||||
/*
|
||||
* Arduino JSON library - Parser Example
|
||||
* Benoit Blanchon 2014 - MIT License
|
||||
*/
|
||||
// Copyright Benoit Blanchon 2014
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#include <JsonParser.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
using namespace ArduinoJson::Parser;
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
char json [] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
JsonParser<16> parser;
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
JsonObject root = parser.parse(json);
|
||||
if (!root.success()) {
|
||||
Serial.println("parseObject() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!root.success())
|
||||
{
|
||||
Serial.println("JsonParser.parse() failed");
|
||||
return;
|
||||
}
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
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);
|
||||
Serial.println(sensor);
|
||||
Serial.println(time);
|
||||
Serial.println(latitude, 6);
|
||||
Serial.println(longitude, 6);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user