Compare commits

..

224 Commits
v1.2 ... v3.1

Author SHA1 Message Date
d460b59b50 Fixed CHANGELOG.md 2014-08-03 15:54:16 +02:00
8e5ea91f8d Updated README 2014-08-03 13:48:22 +02:00
4a8b7d0cb4 Updated code size 2014-08-03 13:23:40 +02:00
96c9b5deee Updated changelog. 2014-08-03 13:18:59 +02:00
8e81b9bb26 Added JsonObjectBase::remove() 2014-08-03 13:16:35 +02:00
817cc09975 Added typedef JsonKey 2014-08-03 13:09:07 +02:00
1bc45f1fd7 Extracted method getMatchingPair() 2014-08-02 16:25:18 +02:00
d2fe9ddf49 Added JsonObjectBase::containsKey() 2014-08-02 16:11:02 +02:00
5cc06180e6 Removed JsonValue::null(), moved the instance to JsonObjectBase 2014-08-02 15:55:46 +02:00
65e8b6d405 Optimized size of JsonObjectBase indexer (-58 bytes) 2014-08-02 15:37:01 +02:00
09294cb5e6 Made EscapedString pure static 2014-08-01 15:32:05 +02:00
158f4600fb Added static EscapedString::printTo 2014-08-01 15:27:58 +02:00
0d28612507 Fixed casting JsonValue to string 2014-08-01 15:23:14 +02:00
7c99d4d63d Reduced usages of EscapedString 2014-08-01 15:22:30 +02:00
1a01800782 Test casting a JsonValue to a JsonArray 2014-08-01 15:06:31 +02:00
6384bc414a Test casting a JsonValue to a float 2014-08-01 14:58:16 +02:00
c10bcee324 Test casting a JsonValue to a double 2014-08-01 14:56:46 +02:00
028ff6676e Test casting a JsonValue to a bool 2014-08-01 14:54:34 +02:00
23b5237f74 Test casting a JsonValue to a long 2014-08-01 14:53:05 +02:00
88510705be Test casting a JsonValue to an int 2014-08-01 14:52:15 +02:00
15d3068d78 Test casting a JsonValue to a string 2014-08-01 14:47:48 +02:00
ae6beb9340 Cleaned JsonValue tests 2014-08-01 14:38:28 +02:00
c1f4128ccd Added a failng test 2014-08-01 14:35:54 +02:00
5fb6edfc91 Cleaned JsonObject unit tests 2014-08-01 14:25:55 +02:00
2771b830b7 Replace the examples with the new API 2014-07-31 20:33:12 +02:00
84aa627038 Updated changelog 2014-07-31 20:28:52 +02:00
4528b8fc95 Use operator[] in example (-68 bytes) 2014-07-31 20:16:14 +02:00
60c6f2db47 Added operator[] 2014-07-31 20:11:55 +02:00
13c386c7a3 Moved JsonValue to namespace ArduinoJson::Generator 2014-07-31 19:57:52 +02:00
7877ee1b4c Replaced set() by operator=() 2014-07-31 19:48:51 +02:00
2c29327ebd Return a JsonValue& instead of a KeyValuePair* (+40 bytes) 2014-07-31 19:42:09 +02:00
85ffb83aa6 Fixed failing test 2014-07-31 18:50:01 +02:00
1ce6661fa6 Created a failing test 2014-07-31 18:16:04 +02:00
68a2ca905e Updated README.md 2014-07-23 20:18:59 +02:00
7e4ab9f31c Added code size 2014-07-23 13:45:07 +02:00
44e5549456 Added code size 2014-07-23 13:29:56 +02:00
3e36831cdc Updated README.md 2014-07-23 12:56:42 +02:00
5129f3400c Added key() and value() shortcuts 2014-07-23 12:56:29 +02:00
0449ee4fd3 Updated README.md 2014-07-23 12:14:59 +02:00
6e4eb45210 Renamed JsonHashTable into JsonObject 2014-07-22 21:02:16 +02:00
abef85218e Renamed ARDUINO_JSON_NO_DEPRECATED_WARNING into ARDUINO_JSON_NO_DEPRECATION_WARNING 2014-07-22 20:33:17 +02:00
649f292ea7 Added comments 2014-07-22 20:28:59 +02:00
805c0741e6 Added comments 2014-07-22 20:14:25 +02:00
0fc54ba54c Added comments 2014-07-21 20:38:08 +02:00
df72419f09 Added comments 2014-07-21 15:20:02 +02:00
d3d0da2d7f Added comments 2014-07-21 14:17:27 +02:00
407d536e06 Added comments 2014-07-21 14:14:31 +02:00
c22473cf37 Removed unused stuff 2014-07-21 11:08:39 +02:00
3e8861b1a0 Moved implemntation of operator[] into JsonObject 2014-07-21 10:52:35 +02:00
f565a9b1b7 Created a Visual Studio project for JsonGenerator 2014-07-21 09:59:47 +02:00
06026cc7d4 Created a Visual Studio project for JsonParser 2014-07-21 09:54:26 +02:00
04f52733c2 Added a test with 3 strings 2014-07-19 16:15:57 +02:00
c06f42659a Updated README.md 2014-07-19 16:05:42 +02:00
e619b8f5bd Updated README.md 2014-07-19 15:57:03 +02:00
1e28217393 Merged parse() and parseToken() 2014-07-19 15:36:01 +02:00
a1e8c8800a Removed uneeded cast operators 2014-07-19 15:34:44 +02:00
00ad540f4e Updated CHANGELOG.md 2014-07-19 15:23:40 +02:00
cd7a7b1533 Fixed bug in JsonArray::begin() and end() 2014-07-19 14:55:16 +02:00
0fe77176e1 Fixed bug in JsonObject::begin() and end() 2014-07-19 14:49:59 +02:00
e94575b4b8 Replaced public inheritance by protected and private 2014-07-19 14:41:29 +02:00
b278d7711b Replaced composition by inheritance 2014-07-19 12:44:27 +02:00
851d21e08c Added JsonObjectIterator 2014-07-18 22:40:50 +02:00
b75d32e980 Renamed JsonHashTable into JsonObject 2014-07-18 16:46:01 +02:00
daa62b3737 Simplified nextSibling() 2014-07-18 16:22:09 +02:00
ed497df9d6 Added JsonToken.cpp 2014-07-18 16:19:14 +02:00
79953730fc Merged nestedTokenCount() and nextSibling() 2014-07-18 16:18:03 +02:00
5d2ffc49fd Fixed JsonArrayIterator unit test 2014-07-18 16:11:21 +02:00
714a37bd59 Replaced JsonToken operators by meaningful methods 2014-07-18 15:54:49 +02:00
4a1d8483cc Added class JsonToken 2014-07-18 15:43:20 +02:00
0d4d77a7cd Updated example 2014-07-17 14:02:51 +02:00
c329572d24 Added JsonArrayIterator (tests are failing) 2014-07-17 13:58:30 +02:00
ca01ecfb49 Added a flag to ignore deprecation warnings 2014-07-17 13:27:40 +02:00
78249a0ada Updated example 2014-07-17 13:23:32 +02:00
45c9ba1191 Renamed JsonObjectBase into JsonPrintable 2014-07-17 13:16:14 +02:00
5e1697f47b JsonArray is now a simple wrapper on top of JsonValue 2014-07-17 13:12:12 +02:00
f2579397d6 JsonHashTable is now a wrapper on to of JsonValue 2014-07-17 12:59:26 +02:00
b6e3a37ad9 Added JsonParserBase::parse() that returns a JsonValue 2014-07-17 12:37:35 +02:00
73eda08dd4 Updated example 2014-07-16 21:10:18 +02:00
6164328892 Renamed JsonArray::getLength() into size() to match std::vector 2014-07-16 14:01:04 +02:00
7487b8cbb7 Defined the DEPRECATED macro 2014-07-16 13:53:56 +02:00
6a868e46bd Made JsonValue inherit from JsonObjectBase 2014-07-16 13:42:36 +02:00
d189bd7140 Added class JsonValue.
Added subscript operator on JsonArray and JsonHashTable
2014-07-16 13:26:11 +02:00
9f07cdcabf Updated CHANGELOG.md 2014-07-15 20:04:21 +02:00
41b5bba939 Updated CHANGELOG.md 2014-07-15 13:50:49 +02:00
7ac4a91591 Added include of JsonParserBase.cpp 2014-07-15 12:56:14 +02:00
5534635feb Fixed case of jsmn.cpp (issue #6) 2014-07-15 12:54:01 +02:00
2e5b959e8b Fixed GCC warnings 2014-07-14 16:13:58 +02:00
9ee3dc638d Update parser size 2014-07-14 16:02:34 +02:00
ccb97fc6e0 Fixed bug JsonObjectBase::getNestedTokenCount() that reads uninitialized token 2014-07-14 15:52:26 +02:00
39c185ae67 Fixed bug in JsonObjectBase::getBoolFromToken() 2014-07-14 14:50:43 +02:00
cf1324c09b Added a test with too few tokens 2014-07-14 14:46:46 +02:00
0b087b7bdb Added a test when token count is too small 2014-07-14 14:35:51 +02:00
dde5a2510b Extracted class JsonParserBase 2014-07-14 13:17:30 +02:00
a42b03ec26 Rewrote tests on hash tables 2014-07-14 12:29:57 +02:00
2f98e59fc6 Cleaned the array tests 2014-07-14 11:48:46 +02:00
f58a8b0ca5 Renamed unit test classes 2014-07-14 10:33:24 +02:00
4f56afe89e Updated changelog 2014-07-09 19:50:44 +02:00
339de21f1c Updated code size 2014-07-09 19:48:55 +02:00
25c428c1e9 Removed useless cast 2014-07-09 13:44:11 +02:00
0045bb3e35 Reduced the size of JsonArrayBase::printTo() by 18 bytes 2014-07-09 13:40:09 +02:00
4e61a839a5 Minor changes 2014-07-09 13:30:08 +02:00
a48fbac7d7 Reduced the size of EscapedString::printTo() by 4 more bytes 2014-07-09 13:19:12 +02:00
af7dd55d34 Reduced the size of EscapedString::printTo() by 4 bytes 2014-07-09 13:16:10 +02:00
525649c416 Reduced the size of EscapedString::printTo() by 26 bytes 2014-07-09 12:59:49 +02:00
1f86016320 Extracted function getSpecialChar() 2014-07-09 12:50:03 +02:00
c38af3e32c Cleaned up 2014-07-08 21:29:19 +02:00
0a0757945e Reduced the size of JsonHashTableBase::printTo() by 12 bytes 2014-07-08 13:49:35 +02:00
e63cde3922 Reducted the size of JsonHashTableBase::printTo() by 18 bytes ! 2014-07-08 13:46:34 +02:00
5bb6cd0fa9 Extracted class JsonArrayBase to reduce code size 2014-07-08 13:38:37 +02:00
bbc18b5ca4 Extracted class JsonHashTableBase to reduce the size of the code. 2014-07-08 13:27:29 +02:00
6d3b70f4a3 Updated encoder size 2014-07-07 20:04:25 +02:00
cbedcdf93b Minor change 2014-07-07 19:50:19 +02:00
6fcf9edf9a Updated README.md 2014-07-07 16:23:54 +02:00
bb11fcba89 Updated the example. 2014-07-07 16:22:43 +02:00
a87b2bf5bf Adde EscapedString to the cpp files 2014-07-07 16:21:34 +02:00
f28997e367 Added a work around for Arduino 1.0.5 2014-07-07 16:21:19 +02:00
42968be535 Updated type sizes 2014-07-07 14:07:24 +02:00
6c1ab912ff Added namespace ArduinoJson::Internals for private types 2014-07-07 14:05:41 +02:00
99521cc718 Removed default template value for DIGITS, because Arduino 1.0.5 refused it 2014-07-07 13:59:31 +02:00
b3613f7137 Use EscapedString for keys in JsonHashTable 2014-07-07 13:48:50 +02:00
1b62502b36 Extracted class EscapedString 2014-07-07 13:38:35 +02:00
adb8fa4d44 Set a default value for DIGITS 2014-07-07 13:28:31 +02:00
3b6ce65054 Reduced the size of JsonValue to 6 bytes ! 2014-07-07 13:27:12 +02:00
be6c4bf4d1 Number of digits is now a template parameter 2014-07-07 13:24:14 +02:00
4e6ad31d6a Reduced the size of JsonValue by removing the pointer to instance methods. 2014-07-06 21:34:46 +02:00
1cec019457 Reduce the size of JsonValue by removing the virtual 2014-07-06 21:28:39 +02:00
2e97dbdedc Reduced the size of JsonValue by no implementing Printable 2014-07-06 21:08:04 +02:00
8f9d3b638f Removed content.asFloat 2014-07-06 20:36:11 +02:00
8be590e591 Added README.md 2014-07-06 14:47:50 +02:00
8baf21b6e8 Minor changes 2014-07-05 21:39:56 +02:00
935cb068ab Updated README.md 2014-07-05 16:09:37 +02:00
efd8c0ff5c Improved the example 2014-07-05 13:10:07 +02:00
757c86ddc5 Simplified the example 2014-07-05 13:09:46 +02:00
0efe8bc74a Added encoder sizes 2014-07-05 12:53:34 +02:00
65d03c9001 Fixed table 2014-07-04 19:15:19 +02:00
df2e640b16 Added README.md 2014-07-04 19:11:04 +02:00
895482de15 Merged the two Visual Studio solutions into one 2014-07-04 14:48:18 +02:00
477c9c2c6e Updated changelog 2014-07-04 14:42:57 +02:00
50b2a1b4a7 Added namespace for the parser 2014-07-03 14:01:45 +02:00
78a920a5fc Now use #pragma once 2014-07-03 13:58:08 +02:00
bae5c36f41 Added namespace 2014-07-03 13:55:38 +02:00
538b15b400 Updated Arduino example 2014-07-03 13:48:11 +02:00
daba65d987 Added overload to add() to specify the double precision 2014-07-03 13:45:53 +02:00
5b1c2047a4 Renamed Print::write() into print() 2014-07-03 13:38:58 +02:00
81c7b9f700 Can now set the double value precision. 2014-07-03 13:35:39 +02:00
2222714d68 Moved sprintf() calls to Print.cpp 2014-07-03 13:21:40 +02:00
dd5cf661e3 Moved Print::write() implementation into Print.cpp 2014-07-03 12:55:53 +02:00
b560a87e15 Change unit tests relying on floating point precision 2014-07-03 12:54:41 +02:00
4d4d775e7a Renamed private method 2014-07-03 12:41:22 +02:00
9bcb5610e8 Updated the changelog 2014-07-02 13:59:13 +02:00
cb0973ab38 Updated Arduino example 2014-07-02 13:54:39 +02:00
c7fb77203b Replace C++11 syntax that what not supported by the Arduino IDE 2014-07-02 13:49:23 +02:00
e87bde6594 Added a JsonValue constructor for float 2014-07-02 13:46:25 +02:00
922b131f8d Splitted the special char tests 2014-07-02 13:24:33 +02:00
ae73a06328 Extracted class StringBuilderTests 2014-07-02 13:16:44 +02:00
61e53a505d Added a test that stores an integer in a JsonValue 2014-07-02 13:06:38 +02:00
937837848c Added a test that stores a long in a JsonValue 2014-07-02 13:02:28 +02:00
1fba9767d3 Renamed private methods 2014-07-02 12:54:22 +02:00
621068260d Renamed union members 2014-07-02 12:52:22 +02:00
e8831c28d9 Added JsonGenerator example for Arduino 2014-07-01 14:08:15 +02:00
a9b8e280fe Moved implementation is a new folder 2014-07-01 13:50:54 +02:00
4d5a7114c1 Added interface Printable. 2014-07-01 13:44:36 +02:00
c3359d3eb9 Renamed JsonSink into Print 2014-07-01 13:36:22 +02:00
c84860e3f4 Renamed JsonSink::append() into write() to match Arduino's Print class 2014-07-01 13:33:00 +02:00
1401665129 Added tests of writeTo() return value 2014-07-01 13:29:54 +02:00
19e007c3f5 Added tests of writeTo() return value 2014-07-01 13:25:21 +02:00
88f630cee5 Added tests on returned value. 2014-07-01 13:20:47 +02:00
a57220debc Changed JsonSink to match Arduino's Print class 2014-07-01 13:15:50 +02:00
69d682ce81 Extracted interface JsonSink. 2014-06-30 19:19:39 +02:00
81f7849c26 Got rid of the switch/case in JsonValue 2014-06-30 18:37:54 +02:00
10068e7b22 Added a test of an empty hash table in a hash table 2014-06-30 12:49:12 +02:00
5b2ee9ed29 Added a test of an empty array in a hash 2014-06-30 12:47:53 +02:00
93ddb9498e Added tests that adds a boolean to a hash table 2014-06-27 13:59:11 +02:00
495efd8629 Added a test that adds a null in a hash table 2014-06-27 13:57:06 +02:00
f548093d86 Added a test of one number in a hash table 2014-06-27 13:54:51 +02:00
5f77949636 Added a test of one string over hash table's capacity 2014-06-27 13:53:55 +02:00
e26cea59e5 Added a test with two strings in a hash table 2014-06-27 13:52:01 +02:00
1800a8e89e Added a test of a nested hash table in an array 2014-06-27 13:49:03 +02:00
1d064d709b Removed the overloads of add() by using a templated type 2014-06-27 13:45:50 +02:00
b7933f85ba Renamed addItem() to add() 2014-06-27 13:43:26 +02:00
0240270492 Extracted class JsonValue 2014-06-27 13:42:26 +02:00
dd8baea373 Fixed the failing tests 2014-06-27 13:24:10 +02:00
568b8988d8 Renamed private members 2014-06-27 13:18:38 +02:00
4f4b35bd41 Small refactoring of the tests 2014-06-27 13:09:52 +02:00
ff4060f5d1 Added a test that adds a string value in a hash 2014-06-27 13:07:38 +02:00
ebb257df6e Added a test of an empty hashtable 2014-06-27 13:00:27 +02:00
48a91a219c Moved writeTo to JsonObjectBase 2014-06-26 13:39:05 +02:00
e75e3b6527 Delete empty file 2014-06-26 13:30:18 +02:00
63ae9ef096 Moved floating point formatting to StringBuilder 2014-06-26 13:28:42 +02:00
33508e3fe0 Minor simplifications 2014-06-26 13:18:28 +02:00
1c4d4bfd2d Added a test with a NULL string 2014-06-26 13:16:22 +02:00
18587d132b Added a test with a NULL string 2014-06-26 13:14:09 +02:00
d12e25bd8a Added a test with special chars 2014-06-26 13:10:52 +02:00
25118ad8c0 Added a test class for StringBuilder.appendEscaped() 2014-06-26 13:05:49 +02:00
7ab728e996 Added a test that appends a string longer that the capacity of the builder 2014-06-26 13:00:14 +02:00
ca99749f28 Added a test that appends 2 string 2014-06-26 12:56:30 +02:00
55487ad668 Added a test that appends special chars 2014-06-26 12:55:40 +02:00
6ea9574330 Added a test that append a normal string 2014-06-26 12:53:58 +02:00
1e44f5522e Added a test that appends an empty string 2014-06-26 12:52:56 +02:00
786fe994aa Added a test class for StringBuilder 2014-06-26 12:50:48 +02:00
6b61617133 Added a test that adds a string with a backslash in it 2014-06-25 13:55:18 +02:00
45dfdbd5e4 Added method appendFormatted() 2014-06-25 13:50:28 +02:00
dd6fd6f198 Added a tests of a string with a double quote in it 2014-06-25 13:47:28 +02:00
ca53abdc41 Moved implementation to the .cpp file 2014-06-25 13:34:47 +02:00
5e4c4a4bdc Renamed the inner types 2014-06-25 13:33:19 +02:00
aa6cf308db Added a test that adds a nested array to an array 2014-06-25 13:31:05 +02:00
b8df795cb5 Added a test that adds a empty nested array in an array 2014-06-25 13:28:56 +02:00
4c387e9062 Extracted base class JsonObjectBase 2014-06-25 13:23:08 +02:00
d57234e92c JsonArray: extracted methods addItem 2014-06-25 13:14:10 +02:00
6f247a5080 Extracted class StringBuilder 2014-06-25 13:02:39 +02:00
d306422ed9 Replace single quotes by double quotes 2014-06-24 21:28:02 +02:00
2a20c5a25c Added a tests that adds a 'null' to an array 2014-06-24 21:24:38 +02:00
1118dd7b53 Added a test that adds a boolean to a full array 2014-06-24 21:19:05 +02:00
3d4f0f741d Added a test that adds two booleans to an array 2014-06-24 21:18:12 +02:00
77a3e1737d Added a test that adds a 'false' to an array 2014-06-24 21:17:12 +02:00
a27bb3097a Generator: added a tests that adds a 'true' to an array 2014-06-24 21:15:07 +02:00
5c119099f3 Generator: added a test of an array with too many numbers 2014-06-24 21:09:25 +02:00
bb705bab63 Generator: added a test with two numbers in an array 2014-06-24 21:07:17 +02:00
22ca52326c Generator: added a test of a float in an array 2014-06-24 13:53:30 +02:00
aa8cff7101 Generator: added a test of a full array 2014-06-24 13:38:48 +02:00
df25a21050 Generator: added a test of an array with 2 strings 2014-06-24 13:36:40 +02:00
f18f554c2f Generator: added a test of one string in an array 2014-06-24 13:34:55 +02:00
c8c1add4ab Generator: added empty array test 2014-06-24 13:19:23 +02:00
3d8b31b1ec Moved all JsonParser code in a sub-folder. 2014-06-24 13:14:07 +02:00
77 changed files with 3963 additions and 1209 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*.sdf
*.user
*.suo
Debug
ipch
*.opensdf

40
ArduinoJson.sln Normal file
View File

@ -0,0 +1,40 @@

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

View File

@ -1,10 +1,72 @@
ArduinoJsonParser change log
============================
Arduino JSON: change log
========================
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()`
Old generator API:
JsonObject<3> root;
root.add("sensor", "gps");
root.add("time", 1351824120);
root.add("data", array);
New generator API:
JsonObject<3> root;
root["sensor"] = "gps";
root["time"] = 1351824120;
root["data"] = array;
v3.0
----
* New parser API, see bellow
* Renamed `JsonHashTable` into `JsonObject`
* Added iterators for `JsonArray` and `JsonObject`
Old parser API:
JsonHashTable root = parser.parseHashTable(json);
char* sensor = root.getString("sensor");
long time = root.getLong("time");
double latitude = root.getArray("data").getDouble(0);
double longitude = root.getArray("data").getDouble(1);
New parser API:
JsonObject root = parser.parse(json);
char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
v2.1
----
* Fixed case `#include "jsmn.cpp"` which caused an error in Linux (issue #6)
* Fixed a buffer overrun in JSON Parser (issue #5)
v2.0
----
* Added JSON encoding (issue #2)
* Renamed the library `ArduinoJsonParser` becomes `ArduinoJson`
**Breaking change**: you need to add the following line at the top of your program.
using namespace ArduinoJson::Parser;
v1.2
----
* Example: changed `char[] json` into `char json[]`. Damn it C# !
* Fixed error in JSON parser example (issue #1)
v1.1
----

View File

@ -1,67 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonArray.h"
#include "JsonHashTable.h"
JsonArray::JsonArray(char* json, jsmntok_t* tokens)
: JsonObjectBase(json, tokens)
{
if (tokens == 0 || tokens[0].type != JSMN_ARRAY)
makeInvalid();
}
/*
* Returns the token for the value at the specified index
*/
jsmntok_t* JsonArray::getToken(int index)
{
// sanity check
if (json == 0 || tokens == 0 || index < 0 || index >= tokens[0].size)
return 0;
// skip first token, it's the whole object
jsmntok_t* currentToken = tokens + 1;
// skip all tokens before the specified index
for (int i = 0; i < index; i++)
{
// move forward: current + nested tokens
currentToken += 1 + getNestedTokenCount(currentToken);
}
return currentToken;
}
JsonArray JsonArray::getArray(int index)
{
return JsonArray(json, getToken(index));
}
bool JsonArray::getBool(int index)
{
return getBoolFromToken(getToken(index));
}
double JsonArray::getDouble(int index)
{
return getDoubleFromToken(getToken(index));
}
JsonHashTable JsonArray::getHashTable(int index)
{
return JsonHashTable(json, getToken(index));
}
long JsonArray::getLong(int index)
{
return getLongFromToken(getToken(index));
}
char* JsonArray::getString(int index)
{
return getStringFromToken(getToken(index));
}

View File

@ -1,42 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014 - MIT License
*/
#ifndef __JSONARRAY_H
#define __JSONARRAY_H
#include "JsonObjectBase.h"
class JsonHashTable;
class JsonArray : public JsonObjectBase
{
template <int N>
friend class JsonParser;
friend class JsonHashTable;
public:
JsonArray() {}
int getLength()
{
return tokens != 0 ? tokens[0].size : 0;
}
JsonArray getArray(int index);
bool getBool(int index);
double getDouble(int index);
JsonHashTable getHashTable(int index);
long getLong(int index);
char* getString(int index);
private:
JsonArray(char* json, jsmntok_t* tokens);
jsmntok_t* getToken(int index);
};
#endif

12
JsonGenerator.cpp Normal file
View File

@ -0,0 +1,12 @@
/*
* 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"

7
JsonGenerator.h Normal file
View File

@ -0,0 +1,7 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonGenerator/JsonArray.h"
#include "JsonGenerator/JsonObject.h"

View File

@ -0,0 +1,45 @@
/*
* 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('\"');
}

View File

@ -0,0 +1,20 @@
/*
* 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&);
};
}
}

28
JsonGenerator/JsonArray.h Normal file
View File

@ -0,0 +1,28 @@
/*
* 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];
};
}
}

View File

@ -0,0 +1,34 @@
/*
* 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;
}

View File

@ -0,0 +1,49 @@
/*
* 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)
{
}
template<typename T>
void add(T value)
{
if (count >= capacity) return;
items[count++] = 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;
};
}
}

View File

@ -0,0 +1,96 @@
<?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>

View File

@ -0,0 +1,69 @@
<?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>

View File

@ -0,0 +1,44 @@
/*
* 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>
{
};
}
}

View File

@ -0,0 +1,92 @@
/*
* 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];
}

View File

@ -0,0 +1,61 @@
/*
* 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;
};
}
}

View File

@ -0,0 +1,31 @@
/*
* 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;
};
}
}

View File

@ -0,0 +1,33 @@
/*
* 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);
}

135
JsonGenerator/JsonValue.h Normal file
View File

@ -0,0 +1,135 @@
/*
* 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=(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 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;
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);
}
};
}
}

35
JsonGenerator/Print.cpp Normal file
View File

@ -0,0 +1,35 @@
/*
* 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

28
JsonGenerator/Print.h Normal file
View File

@ -0,0 +1,28 @@
/*
* 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

24
JsonGenerator/Printable.h Normal file
View File

@ -0,0 +1,24 @@
/*
* 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

212
JsonGenerator/README.md Normal file
View File

@ -0,0 +1,212 @@
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);
#### 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&lt;N&gt; | 8 + 6 x N |
| JsonObject&lt;N&gt; | 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 |

View File

@ -0,0 +1,17 @@
/*
* 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;
}

View File

@ -0,0 +1,31 @@
/*
* 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;
};
}
}

View File

@ -0,0 +1,95 @@
/*
* 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);
}
};
}

View File

@ -0,0 +1,173 @@
/*
* 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> arr;
char buffer[256];
public:
TEST_METHOD(Empty)
{
outputMustBe("[]");
}
TEST_METHOD(Null)
{
add((char*)0);
outputMustBe("[null]");
}
TEST_METHOD(OneString)
{
add("hello");
outputMustBe("[\"hello\"]");
}
TEST_METHOD(TwoStrings)
{
add("hello");
add("world");
outputMustBe("[\"hello\",\"world\"]");
}
TEST_METHOD(OneStringOverCapacity)
{
add("hello");
add("world");
add("lost");
outputMustBe("[\"hello\",\"world\"]");
}
TEST_METHOD(OneDoubleDefaultDigits)
{
add(3.14159265358979323846);
outputMustBe("[3.14]");
}
TEST_METHOD(OneDoubleFourDigits)
{
add<4>(3.14159265358979323846);
outputMustBe("[3.1416]");
}
TEST_METHOD(OneInteger)
{
add(1);
outputMustBe("[1]");
}
TEST_METHOD(TwoIntegers)
{
add(1);
add(2);
outputMustBe("[1,2]");
}
TEST_METHOD(OneIntegerOverCapacity)
{
add(1);
add(2);
add(3);
outputMustBe("[1,2]");
}
TEST_METHOD(OneTrue)
{
add(true);
outputMustBe("[true]");
}
TEST_METHOD(OneFalse)
{
add(false);
outputMustBe("[false]");
}
TEST_METHOD(TwoBooleans)
{
add(false);
add(true);
outputMustBe("[false,true]");
}
TEST_METHOD(OneBooleanOverCapacity)
{
add(false);
add(true);
add(false);
outputMustBe("[false,true]");
}
TEST_METHOD(OneEmptyNestedArray)
{
addNested(JsonArray<1>());
outputMustBe("[[]]");
}
TEST_METHOD(OneEmptyNestedHash)
{
addNested(JsonHashTable<1>());
outputMustBe("[{}]");
}
TEST_METHOD(OneNestedArrayWithOneInteger)
{
JsonArray<1> nestedArray;
nestedArray.add(1);
addNested(nestedArray);
outputMustBe("[[1]]");
}
private:
void addNested(Printable& value)
{
arr.add<Printable&>(value);
}
template<typename T>
void add(T value)
{
arr.add(value);
}
template<int DIGITS>
void add(double value)
{
arr.add<DIGITS>(value);
}
void outputMustBe(const char* expected)
{
size_t n = arr.printTo(buffer, sizeof(buffer));
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), n);
}
};
}

View File

@ -0,0 +1,103 @@
<?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="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>

View File

@ -0,0 +1,40 @@
<?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>
</ItemGroup>
</Project>

View File

@ -0,0 +1,73 @@
/*
* 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);
}
};
}

View File

@ -0,0 +1,152 @@
/*
* 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);
}
};
}

View File

@ -0,0 +1,78 @@
/*
* 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;
Printable& actual = value;
Assert::AreEqual((void*) &expected, (void*) &actual);
}
};
}

View File

@ -0,0 +1,103 @@
/*
* 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);
}
};
}

View File

@ -0,0 +1,85 @@
/*
* 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);
}
};
}

View File

@ -1,84 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonArray.h"
#include "JsonHashTable.h"
#include <string.h> // for strcmp()
JsonHashTable::JsonHashTable(char* json, jsmntok_t* tokens)
: JsonObjectBase(json, tokens)
{
if (tokens == 0 || tokens[0].type != JSMN_OBJECT)
makeInvalid();
}
/*
* Returns the token for the value associated with the specified key
*/
jsmntok_t* JsonHashTable::getToken(const char* desiredKey)
{
// sanity check
if (json == 0 || tokens == 0 || desiredKey == 0)
return 0;
// skip first token, it's the whole object
jsmntok_t* currentToken = tokens + 1;
// scan each keys
for (int i = 0; i < tokens[0].size / 2 ; i++)
{
// get key token string
char* key = getStringFromToken(currentToken);
// compare with desired name
if (strcmp(desiredKey, key) == 0)
{
// return the value token that follows the key token
return currentToken + 1;
}
// move forward: key + value + nested tokens
currentToken += 2 + getNestedTokenCount(currentToken + 1);
}
// nothing found, return NULL
return 0;
}
bool JsonHashTable::containsKey(const char* key)
{
return getToken(key) != 0;
}
JsonArray JsonHashTable::getArray(const char* key)
{
return JsonArray(json, getToken(key));
}
bool JsonHashTable::getBool(const char* key)
{
return getBoolFromToken(getToken(key));
}
double JsonHashTable::getDouble(const char* key)
{
return getDoubleFromToken(getToken(key));
}
JsonHashTable JsonHashTable::getHashTable(const char* key)
{
return JsonHashTable(json, getToken(key));
}
long JsonHashTable::getLong(const char* key)
{
return getLongFromToken(getToken(key));
}
char* JsonHashTable::getString(const char* key)
{
return getStringFromToken(getToken(key));
}

View File

@ -1,39 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014 - MIT License
*/
#ifndef __JSONHASHTABLE_H
#define __JSONHASHTABLE_H
#include "JsonObjectBase.h"
class JsonArray;
class JsonHashTable : public JsonObjectBase
{
template <int N>
friend class JsonParser;
friend class JsonArray;
public:
JsonHashTable() {}
bool containsKey(const char* key);
JsonArray getArray(const char* key);
bool getBool(const char* key);
double getDouble(const char* key);
JsonHashTable getHashTable(const char* key);
long getLong(const char* key);
char* getString(const char* key);
private:
JsonHashTable(char* json, jsmntok_t* tokens);
jsmntok_t* getToken(const char* key);
};
#endif

View File

@ -1,67 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014
* MIT License
*/
#include "JsonObjectBase.h"
#include <stdlib.h> // for strtol, strtod
int JsonObjectBase::getNestedTokenCount(jsmntok_t* token)
{
int end = token->end;
int count = 0;
token++;
while (token->start < end)
{
token++;
count++;
}
return count;
}
bool JsonObjectBase::getBoolFromToken(jsmntok_t* token)
{
if (token->type != JSMN_PRIMITIVE) return 0;
// "true"
if (json[token->start] == 't') return true;
// "false"
if (json[token->start] == 'f') return false;
// "null"
if (json[token->start] == 'n') return false;
// number
return strtol(json + token->start, 0, 0) != 0;
}
double JsonObjectBase::getDoubleFromToken(jsmntok_t* token)
{
if (token == 0 || token->type != JSMN_PRIMITIVE) return 0;
return strtod(json + token->start, 0);
}
long JsonObjectBase::getLongFromToken(jsmntok_t* token)
{
if (token == 0 || token->type != JSMN_PRIMITIVE) return 0;
return strtol(json + token->start, 0, 0);
}
char* JsonObjectBase::getStringFromToken(jsmntok_t* token)
{
if (token == 0 || token->type != JSMN_PRIMITIVE && token->type != JSMN_STRING)
return 0;
// add null terminator to the string
json[token->end] = 0;
return json + token->start;
}

View File

@ -1,52 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014
* MIT License
*/
#ifndef __JSONOBJECTBASE_H
#define __JSONOBJECTBASE_H
#include "utility/jsmn.h"
class JsonObjectBase
{
public:
JsonObjectBase()
{
makeInvalid();
}
bool success()
{
return json != 0 && tokens != 0;
}
protected:
JsonObjectBase(char* json, jsmntok_t* tokens)
{
this->json = json;
this->tokens = tokens;
}
void makeInvalid()
{
json = 0;
tokens = 0;
}
static int getNestedTokenCount(jsmntok_t* token);
bool getBoolFromToken(jsmntok_t* token);
double getDoubleFromToken(jsmntok_t* token);
long getLongFromToken(jsmntok_t* token);
char* getStringFromToken(jsmntok_t* token);
char* json;
jsmntok_t* tokens;
};
#endif

13
JsonParser.cpp Normal file
View File

@ -0,0 +1,13 @@
/*
* 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"

View File

@ -3,67 +3,4 @@
* Benoit Blanchon 2014 - MIT License
*/
#ifndef __JSONPARSER_H
#define __JSONPARSER_H
#include "JsonHashTable.h"
#include "JsonArray.h"
/*
* The JSON parser.
*
* You need to specifiy the number of token to be allocated for that parser.
* Values from 16 to 32 are recommended.
* The parser size will be MAX_TOKEN*8 bytes.
* Don't forget that the memory size of standard Arduino board is only 2KB
*
* CAUTION: JsonArray and JsonHashTable contain pointers to tokens of the
* JsonParser, so they need the JsonParser to be in memory to work.
* As a result, you must not create JsonArray and JsonHashTable that have a
* longer life that the JsonParser.
*/
template <int MAX_TOKENS>
class JsonParser
{
public:
/*
* Parse the JSON string and return a array.
*
* The content of the string may be altered to add '\0' at the
* end of string tokens
*/
JsonArray parseArray(char* json)
{
return JsonArray(json, parse(json));
}
/*
* Parse the JSON string and return a array.
*
* The content of the string may be altered to add '\0' at the
* end of string tokens
*/
JsonHashTable parseHashTable(char* json)
{
return JsonHashTable(json, parse(json));
}
private:
jsmntok_t* parse(char* json)
{
jsmn_parser parser;
jsmn_init(&parser);
if (JSMN_SUCCESS != jsmn_parse(&parser, json, tokens, MAX_TOKENS))
return 0;
return tokens;
}
jsmntok_t tokens[MAX_TOKENS];
};
#endif
#include "JsonParser/JsonParser.h"

14
JsonParser/JsonArray.cpp Normal file
View File

@ -0,0 +1,14 @@
/*
* 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);
}

103
JsonParser/JsonArray.h Normal file
View File

@ -0,0 +1,103 @@
/*
* 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);
}
};
}
}

View File

@ -0,0 +1,46 @@
/*
* 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);
}
};
}
}

15
JsonParser/JsonObject.cpp Normal file
View File

@ -0,0 +1,15 @@
/*
* 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);
}

102
JsonParser/JsonObject.h Normal file
View File

@ -0,0 +1,102 @@
/*
* 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;
}
}

View File

@ -0,0 +1,58 @@
/*
* 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();
}
};
}
}

37
JsonParser/JsonPair.h Normal file
View File

@ -0,0 +1,37 @@
/*
* 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();
}
};
}
}

35
JsonParser/JsonParser.h Normal file
View File

@ -0,0 +1,35 @@
/*
* 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];
};
}
}

View File

@ -0,0 +1,96 @@
<?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>

View File

@ -15,45 +15,54 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\JsonArray.h">
<ClInclude Include="JsonParserBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonHashTable.h">
<ClInclude Include="JsonToken.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonObjectBase.h">
<ClInclude Include="JsonValue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonParser.h">
<ClInclude Include="JsonParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\utility\jsmn.h">
<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="..\JsonArray.cpp">
<ClCompile Include="jsmn.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonHashTable.cpp">
<ClCompile Include="JsonArray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonObjectBase.cpp">
<ClCompile Include="JsonObject.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\utility\jsmn.cpp">
<ClCompile Include="JsonParserBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestHashTableExample.cpp">
<ClCompile Include="JsonToken.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestArrayExample.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestGbathreeStrings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestArrays.cpp">
<ClCompile Include="JsonValue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@ -0,0 +1,20 @@
/*
* 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);
}

View File

@ -0,0 +1,49 @@
/*
* 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;
};
}
}

27
JsonParser/JsonToken.cpp Normal file
View File

@ -0,0 +1,27 @@
/*
* 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);
}

100
JsonParser/JsonToken.h Normal file
View File

@ -0,0 +1,100 @@
/*
* 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;
};
}
}

110
JsonParser/JsonValue.cpp Normal file
View File

@ -0,0 +1,110 @@
/*
* 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();
}

72
JsonParser/JsonValue.h Normal file
View File

@ -0,0 +1,72 @@
/*
* 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);
};
}
}

250
JsonParser/README.md Normal file
View File

@ -0,0 +1,250 @@
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 |

View File

@ -1,13 +1,19 @@
/*
* 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(TestGbathreeSample1)
TEST_CLASS(GbathreeBug)
{
char json[1024];
JsonParser<200> parser;

View File

@ -0,0 +1,67 @@
/*
* 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);
}
}
};
}

View File

@ -0,0 +1,195 @@
/*
* 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));
}
};
}

View File

@ -0,0 +1,71 @@
/*
* 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++;
}
}
};
}

View File

@ -0,0 +1,171 @@
/*
* 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));
}
};
}

View File

@ -14,6 +14,7 @@
<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">
@ -55,7 +56,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>ARDUINO_JSON_NO_DEPRECATION_WARNING;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
@ -84,21 +85,16 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\JsonArray.h" />
<ClInclude Include="..\JsonHashTable.h" />
<ClInclude Include="..\JsonObjectBase.h" />
<ClInclude Include="..\JsonParser.h" />
<ClInclude Include="..\utility\jsmn.h" />
<ClCompile Include="JsonObjectIteratorTests.cpp" />
<ClCompile Include="JsonArrayTests.cpp" />
<ClCompile Include="JsonArrayIteratorTests.cpp" />
<ClCompile Include="JsonObjectTests.cpp" />
<ClCompile Include="GbathreeBug.cpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\JsonArray.cpp" />
<ClCompile Include="..\JsonHashTable.cpp" />
<ClCompile Include="..\JsonObjectBase.cpp" />
<ClCompile Include="..\utility\jsmn.cpp" />
<ClCompile Include="TestArrayExample.cpp" />
<ClCompile Include="TestArrays.cpp" />
<ClCompile Include="TestHashTableExample.cpp" />
<ClCompile Include="TestGbathreeStrings.cpp" />
<ProjectReference Include="..\JsonParser\JsonParser.vcxproj">
<Project>{c15274de-2695-4dfe-8520-4424223fe6da}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -0,0 +1,34 @@
<?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>

View File

@ -0,0 +1,25 @@
#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);
}
};
}

430
README.md
View File

@ -1,416 +1,58 @@
An efficient JSON parser for Arduino
====================================
Arduino JSON library
====================
This library is an thin C++ wrapper around the *jsmn* tokenizer: http://zserge.com/jsmn.html
*An elegant and efficient JSON library for embedded systems.*
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 on any other C++ project.
It's design to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
Features
--------
* Based on the well-proven [jsmn](http://zserge.com/jsmn.html) tokenizer
* Supports nested objects
* Works with fixed memory allocation : no `malloc()`
* Low footprint
* JSON decoding: [more details here](/JsonParser/)
* JSON encoding: [more details here](/JsonGenerator/)
* Elegant API, very easy to use
* Fixed memory allocation (no malloc)
* Small footprint
* MIT License
Feature comparison
------------------
Example
-------
| 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%) |
char json[] = "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}";
"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).
JsonParser<32> parser;
"Encoder size" was measured with a program generating `{"sensor":"outdoor","value":25.6}`.
[Source files are here](https://gist.github.com/bblanchon/60224e9dcfeab4ddc7e9).
JsonHashTable hashTable = parser.parseHashTable(json);
In each case the target platform was an Arduino Duemilanove and Arduino IDE 1.0.5 was used.
if (!hashTable.success())
{
return;
}
Links: [json-arduino](https://github.com/not404/json-arduino), [aJson](https://github.com/interactive-matter/aJson)
char* name = hashTable.getString("Name");
JsonArray skills = hashTable.getArray("Skills");
int age = hashTable.getLong("Age");
bool online = hashTable.getBool("Online");
How to use ?
-------------
### 1. Install the library
Download the library and extract it to:
<your Arduino Sketch folder>/libraries/ArduinoJsonParser
### 2. Import in your sketch
Just add the following line on the top of your `.ino` file:
#include <JsonParser.h>
### 3. Create a parser
To extract data from the JSON string, you need to create a `JsonParser`, and specify the number of token you allocate for the parser itself:
JsonParser<32> parser;
> #### How to choose the number of tokens ?
> A token is an element of the JSON object: either a key, a value, an hash-table or an array.
> As an example the `char json[]` on the top of this page contains 12 tokens (don't forget to count 1 for the whole object and 1 more for the array itself).
> The more tokens you allocate, the more complex the JSON can be, but also the more memory is occupied.
> Each token takes 8 bytes, so `sizeof(JsonParser<32>)` is 256 bytes which is quite big in an Arduino with only 2KB of RAM.
> Don't forget that you also have to store the JSON string in RAM and it's probably big.
> 32 tokens may seem small, but it's very decent for an 8-bit processor, you wouldn't get better results with other JSON libraries.
### 4. Extract data
To use this library, you need to know beforehand what is the type of data contained in the JSON string, which is very likely.
The root object has to be either a hash-table (like `{"key":"value"}`) or an array (like `[1,2]`).
The nested objects can be either arrays, booleans, hash-tables, numbers or strings.
If you need other type, you can get the string value and parse it yourself.
#### Hash-table
Consider we have a `char json[]` containing to the following JSON string:
{
"Name":"Blanchon",
"Skills":[
"C",
"C++",
"C#"],
"Age":32,
"Online":true
}
In this case the root object of the JSON string is a hash-table, so you need to extract a `JsonHashTable`:
JsonHashTable root = parser.parseHashTable(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* name = hashTable.getString("Name");
JsonArray skills = hashTable.getArray("Skills");
int age = hashTable.getLong("Age");
bool online = hashTable.getBool("Online");
#### 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.parseArray(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:
JsonArray row0 = root.getArray(0);
double a = row0.getDouble(0);
or simply:
double a = root.getArray(0).getDouble(0);
Common pitfalls
---------------
### 1. Not enough tokens
By design, the library has no way to tell you why `JsonParser::parseArray()` or `JsonParser::parseHashTable()` failed.
There are basically two reasons why they may fail:
1. the JSON string is invalid
2. the JSON string contains more tokens that the parser can store
So, if you are sure the JSON string is correct and you still can't parse it, you should slightly increase the number of token of the parser.
### 2. Not enough memory
You may go into unpredictable trouble if you allocate more memory than your processor really has.
It's a very common issue in embedded development.
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
For example, don't do this:
char json[1024]; // 1 KB
JsonParser<64> parser; // 512 B
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
That is why an 8-bit processor is not able to parse long and complex JSON strings.
### 3. JsonParser not in memory
To reduce the memory consumption, `JsonArray` and `JsonHashTable` contains pointer to the token that are inside the `JsonParser`. This can only work if the `JsonParser` is still in memory.
For example, don't do this:
JsonArray getArray(char* json)
{
JsonParser<16> parser;
return parser.parseArray(parser);
}
because the local variable `parser` will be *removed* from memory when the function `getArray()` returns, and the pointer inside `JsonArray` will point to an invalid location.
### 4. JSON string is altered
This will probably never be an issue, but you need to be aware of this feature.
When you pass a `char[]` to `JsonParser::parseArray()` or `JsonParser::parseHashTable()`, the content of the string will be altered to add `\0` at the end of the tokens.
This is because we want functions like `JsonArray::getString()` to return a null-terminating string without any memory allocation.
Memory usage
Testimonials
------------
Here are the size of the main classes of the library.
From Arduino's Forum user `jflaplante`:
> I tried the [aJson and json-arduino] before trying your library. I always ran into memory problem after a while.
> I have no such problem so far with your library. It is working perfectly with my web services.
This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor.
From Arduino's Forum user `gbathree`:
> Thanks so much - this is an awesome library! If you want to see what we're doing with it - the project is located at www.photosynq.org.
<table>
<tr>
<th>Type</th>
<th>Size in bytes</th>
</tr>
<tr>
<td>Parser&lt;N&gt;</td>
<td>8 x N</td>
</tr>
<tr>
<td>JsonArray</td>
<td>4</td>
</tr>
<tr>
<td>JsonHashTable</td>
<td>4</td>
</tr>
</table>
From StackOverflow user `thegreendroid`:
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
Code size
---------
Theses tables has been created by analyzing the map file generated by AVR-GCC after adding `-Wl,-Map,foo.map` to the command line.
As you'll see the code size if between 1680 and 3528 bytes, depending on the features you use.
### Minimum setup
<table>
<tr>
<th>Function</th>
<th>Size in bytes</th>
</tr>
<tr>
<td>strcmp(char*,char*)</td>
<td>18</td>
</tr>
<tr>
<td>jsmn_init(jsmn_parser*)</td>
<td>20</td>
</tr>
<tr>
<td>jsmn_parse(jsmn_parser*, char const*, jsmntok_t*, unsigned int)</td>
<td>960</td>
</tr>
<tr>
<td>JsonParser::parse(char*)</td>
<td>106</td>
</tr>
<tr>
<td>JsonObjectBase::getNestedTokenCount(jsmntok_t*)</td>
<td>84</td>
</tr>
<tr>
<td>JsonObjectBase::getStringFromToken(jsmntok_t*)</td>
<td>68</td>
</tr>
<tr>
<td>JsonArray::JsonArray(char*, jsmntok_t*)</td>
<td>42</td>
</tr>
<tr>
<td>JsonArray::getToken(int)</td>
<td>112</td>
</tr>
<tr>
<td>JsonArray::getString(int)</td>
<td>18</td>
</tr>
<tr>
<td>JsonHashTable::JsonHashTable(char*, jsmntok_t*)</td>
<td>42</td>
</tr>
<tr>
<td>JsonHashTable::getToken(char*)</td>
<td>180</td>
</tr>
<tr>
<td>JsonHashTable::getString(char*)</td>
<td>18</td>
</tr>
<tr>
<td>TOTAL</td>
<td>1680</td>
</tr>
</table>
### Additional space to parse nested objects
<table>
<tr>
<th>Function</th>
<th>Size in bytes</th>
</tr>
<tr>
<td>JsonArray::getArray(int)</td>
<td>42</td>
</tr>
<tr>
<td>JsonArray::getHashTable(int)</td>
<td>64</td>
</tr>
<tr>
<td>JsonHashTable::getArray(char*)</td>
<td>64</td>
</tr>
<tr>
<td>JsonHashTable::getHashTable(char*)</td>
<td>42</td>
</tr>
<tr>
<td>TOTAL</td>
<td>212</td>
</tr>
</table>
### Additional space to parse `bool` values
<table>
<tr>
<th>Function</th>
<th>Size in bytes</th>
</tr>
<tr>
<td>JsonObjectBase::getBoolFromToken(jsmntok_t*)</td>
<td>82</td>
</tr>
<tr>
<td>JsonArray::getBool(int)</td>
<td>18</td>
</tr>
<tr>
<td>JsonHashTable::getBool(char*)</td>
<td>18</td>
</tr>
<tr>
<td>TOTAL</td>
<td>130</td>
</tr>
</table>
### Additional space to parse `double` values
<table>
<tr>
<th>Function</th>
<th>Size in bytes</th>
</tr>
<tr>
<td>strtod(char*,int)</td>
<td>704</td>
</tr>
<tr>
<td>JsonObjectBase::getDoubleFromToken(jsmntok_t*)</td>
<td>44</td>
</tr>
<tr>
<td>JsonArray::getDouble(int)</td>
<td>18</td>
</tr>
<tr>
<td>JsonHashTable::getDouble(char*)</td>
<td>18</td>
</tr>
<tr>
<td>TOTAL</td>
<td>796</td>
</tr>
</table>
### Additional space to parse `long` values
<table>
<tr>
<th>Function</th>
<th>Size in bytes</th>
</tr>
<tr>
<td>strtol(char*,char**,int)</td>
<td>606</td>
</tr>
<tr>
<td>JsonObjectBase::getLongFromToken(jsmntok_t*)</td>
<td>56</td>
</tr>
<tr>
<td>JsonArray::getLong(int)</td>
<td>18</td>
</tr>
<tr>
<td>JsonHashTable::getLong(char*)</td>
<td>18</td>
</tr>
<tr>
<td>TOTAL</td>
<td>710</td>
</tr>
</table>
Links
Related blog posts
-----
* [The project for which I made me this library](http://blog.benoitblanchon.fr/rfid-payment-terminal/)
* [Blog post on the motivation for this library](http://blog.benoitblanchon.fr/arduino-json-parser/)
* [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/)

View File

@ -0,0 +1,29 @@
/*
* Arduino JSON library - Generator example
* Benoit Blanchon 2014 - MIT License
*/
#include <JsonGenerator.h>
using namespace ArduinoJson::Generator;
void setup()
{
Serial.begin(9600);
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<3> root;
root["sensor"] = "gps";
root["time"] = 1351824120;
root["data"] = array;
Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
}
void loop()
{
}

View File

@ -1,94 +1,40 @@
/*
* malloc-free JSON parser for Arduino
* Arduino JSON library - Parser Example
* Benoit Blanchon 2014 - MIT License
*/
#include <JsonParser.h>
void ParseAnObject()
{
char json[] = "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}";
JsonParser<32> parser;
Serial.print("Parse ");
Serial.println(json);
JsonHashTable hashTable = parser.parseHashTable(json);
if (!hashTable.success())
{
Serial.println("JsonParser.parseHashTable() failed");
return;
}
char* name = hashTable.getString("Name");
Serial.print("name=");
Serial.println(name);
JsonArray skills = hashTable.getArray("Skills");
Serial.println("skills:");
for (int i = 0; i < skills.getLength(); i++)
{
char* value = skills.getString(i);
Serial.print(i);
Serial.print(" ");
Serial.println(value);
}
int age = hashTable.getLong("Age");
Serial.print("age=");
Serial.println(age);
bool online = hashTable.getBool("Online");
Serial.print("online=");
Serial.println(online);
}
void ParseAnArray()
{
char json[] = "[[1.2,3.4],[5.6,7.8]]";
JsonParser<32> parser;
Serial.print("Parse ");
Serial.println(json);
JsonArray array = parser.parseArray(json);
if (!array.success())
{
Serial.println("JsonParser.parseArray() failed");
return;
}
for (int i = 0; i < array.getLength(); i++)
{
Serial.println(i);
JsonArray innerArray = array.getArray(i);
for (int j = 0; j < innerArray.getLength(); j++)
{
double value = innerArray.getDouble(j);
Serial.print(" ");
Serial.print(j);
Serial.print("=");
Serial.println(value);
}
}
}
using namespace ArduinoJson::Parser;
void setup()
{
Serial.begin(9600);
ParseAnObject();
ParseAnArray();
char json [] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
JsonParser<16> parser;
JsonObject root = parser.parse(json);
if (!root.success())
{
Serial.println("JsonParser.parse() failed");
return;
}
char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
Serial.println(sensor);
Serial.println(time);
Serial.println(latitude, 6);
Serial.println(longitude, 6);
}
void loop()
{
}
}

View File

@ -1,10 +1,6 @@
JsonParser KEYWORD1
JsonArray KEYWORD1
JsonHashTable KEYWORD1
getArray KEYWORD2
getBool KEYWORD2
getDouble KEYWORD2
getHashTableKEYWORD2
getLong KEYWORD2
parseArray KEYWORD2
parseHashTable KEYWORD2
JsonObject KEYWORD1
add KEYWORD2
parse KEYWORD2
success KEYWORD2

5
tests/.gitignore vendored
View File

@ -1,5 +0,0 @@
/*.sdf
/*.user
/*.suo
/Debug
/ipch

View File

@ -1,22 +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}") = "ArduinoJsonParserTests", "ArduinoJsonParserTests.vcxproj", "{4DD596EF-0185-4AB4-A3C2-F20C496F7806}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,50 +0,0 @@
#include "CppUnitTest.h"
#include "JsonParser.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ArduinoJsonParserTests
{
TEST_CLASS(TestArrayExample)
{
char json[128];
JsonParser<32> parser;
JsonArray array;
public:
TEST_METHOD_INITIALIZE(Initialize)
{
strcpy(json, "[[1.2,3.4],[5.6,7.8]]");
array = parser.parseArray(json);
}
TEST_METHOD(Array_Success_ReturnsTrue)
{
Assert::IsTrue(array.success());
}
TEST_METHOD(Array_GetLength_Returns2)
{
Assert::AreEqual(2, array.getLength());
}
TEST_METHOD(Array_GetArray0_ReturnsInnerArray0)
{
JsonArray innerArray = array.getArray(0);
Assert::AreEqual(2, innerArray.getLength());
Assert::AreEqual(1.2, innerArray.getDouble(0));
Assert::AreEqual(3.4, innerArray.getDouble(1));
}
TEST_METHOD(Array_GetArray1_ReturnsInnerArray1)
{
JsonArray innerArray = array.getArray(1);
Assert::AreEqual(2, innerArray.getLength());
Assert::AreEqual(5.6, innerArray.getDouble(0));
Assert::AreEqual(7.8, innerArray.getDouble(1));
}
};
}

View File

@ -1,141 +0,0 @@
#include "CppUnitTest.h"
#include "JsonParser.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ArduinoJsonParserTests
{
TEST_CLASS(TestArrays)
{
JsonParser<32> parser;
public:
TEST_METHOD(EmptyString)
{
char json[] = "";
JsonArray array = parser.parseArray(json);
Assert::IsFalse(array.success());
}
TEST_METHOD(EmptyArray)
{
char json[] = "[]";
JsonArray array = parser.parseArray(json);
Assert::IsTrue(array.success());
}
TEST_METHOD(TooFewClosingBrackets)
{
char json[] = "[[]";
JsonArray array = parser.parseArray(json);
Assert::IsFalse(array.success());
}
TEST_METHOD(TooManyClosingBrackets)
{
char json[] = "[]]";
JsonArray array = parser.parseArray(json);
Assert::IsFalse(array.success());
}
TEST_METHOD(OneDimensionArray)
{
char json [] = "[0,0]";
JsonArray array = parser.parseArray(json);
Assert::IsTrue(array.success());
Assert::AreEqual(2, array.getLength());
for (int i = 0; i < 2; i++)
{
Assert::AreEqual(0L, array.getLong(i));
}
}
TEST_METHOD(TwoDimensionsArray)
{
char json[] = "[[0,0],[0,0]]";
JsonArray array1 = parser.parseArray(json);
Assert::IsTrue(array1.success());
Assert::AreEqual(2, array1.getLength());
for (int i = 0; i < 2; i++)
{
JsonArray array2 = array1.getArray(i);
Assert::AreEqual(2, array2.getLength());
for (int j = 0; j < 2; j++)
{
Assert::AreEqual(0L, array2.getLong(j));
}
}
}
TEST_METHOD(TreeDimensionsArray)
{
char json[] = "[[[0,0],[0,0]],[[0,0],[0,0]]]";
JsonArray array1 = parser.parseArray(json);
Assert::IsTrue(array1.success());
Assert::AreEqual(2, array1.getLength());
for (int i = 0; i < 2; i++)
{
JsonArray array2 = array1.getArray(i);
Assert::AreEqual(2, array2.getLength());
for (int j = 0; j < 2; j++)
{
JsonArray array3 = array2.getArray(j);
Assert::AreEqual(2, array3.getLength());
for (int k = 0; k < 2; k++)
{
Assert::AreEqual(0L, array3.getLong(k));
}
}
}
}
TEST_METHOD(OneDimensionArrayInHashTable)
{
char json[] = "{a:[0,0],b:[0,0]}";
JsonHashTable root = parser.parseHashTable(json);
Assert::IsTrue(root.success());
JsonArray arrayA = root.getArray("a");
Assert::IsTrue(arrayA.success());
Assert::AreEqual(2, arrayA.getLength());
JsonArray arrayB = root.getArray("b");
Assert::IsTrue(arrayB.success());
Assert::AreEqual(2, arrayB.getLength());
}
TEST_METHOD(TwoDimensionsArrayInHashTable)
{
char json[] = "{a:[[0],[0]],b:[[0],[0]]}";
JsonHashTable root = parser.parseHashTable(json);
Assert::IsTrue(root.success());
JsonArray arrayA = root.getArray("a");
Assert::IsTrue(arrayA.success());
Assert::AreEqual(2, arrayA.getLength());
JsonArray arrayB = root.getArray("b");
Assert::IsTrue(arrayB.success());
Assert::AreEqual(2, arrayB.getLength());
}
};
}

View File

@ -1,61 +0,0 @@
#include "CppUnitTest.h"
#include "JsonParser.h"
#include <string>
using namespace std;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ArduinoJsonParserTests
{
TEST_CLASS(TestHashTableExample)
{
char json[128];
JsonParser<32> parser;
JsonHashTable hashTable;
public:
TEST_METHOD_INITIALIZE(Initialize)
{
strcpy(json, "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}");
hashTable = parser.parseHashTable(json);
}
TEST_METHOD(HashTable_Success_ReturnsTrue)
{
Assert::IsTrue(hashTable.success());
}
TEST_METHOD(HashTable_GetString_ReturnsExpectedValue)
{
string name = hashTable.getString("Name");
Assert::AreEqual(name, string("Blanchon"));
}
TEST_METHOD(HashTable_GetArray_ReturnsExpectedValue)
{
JsonArray skills = hashTable.getArray("Skills");
string skill0 = skills.getString(0);
Assert::AreEqual(skill0, string("C"));
string skill1 = skills.getString(1);
Assert::AreEqual(skill1, string("C++"));
string skill2 = skills.getString(2);
Assert::AreEqual(skill2, string("C#"));
}
TEST_METHOD(HashTable_GetLong_ReturnsExpectedValue)
{
int age = hashTable.getLong("Age");
Assert::AreEqual(32, age);
}
TEST_METHOD(HashTable_GetBool_ReturnsExpectedValue)
{
bool online = hashTable.getBool("Online");
Assert::AreEqual(true, online);
}
};
}