Compare commits

...

458 Commits
v2.1 ... v4.0

Author SHA1 Message Date
348357eb04 Merge branch '4.0'
Conflicts:
	JsonGenerator.cpp
	JsonGenerator.h
	JsonGenerator/EscapedString.cpp
	JsonGenerator/EscapedString.h
	JsonGenerator/IndentedPrint.cpp
	JsonGenerator/IndentedPrint.h
	JsonGenerator/JsonArray.h
	JsonGenerator/JsonArrayBase.cpp
	JsonGenerator/JsonArrayBase.h
	JsonGenerator/JsonObject.h
	JsonGenerator/JsonObjectBase.cpp
	JsonGenerator/JsonObjectBase.h
	JsonGenerator/JsonPrettyPrint.cpp
	JsonGenerator/JsonPrettyPrint.h
	JsonGenerator/JsonPrintable.cpp
	JsonGenerator/JsonPrintable.h
	JsonGenerator/JsonValue.cpp
	JsonGenerator/JsonValue.h
	JsonGenerator/Print.cpp
	JsonGenerator/Print.h
	JsonGenerator/Printable.h
	JsonGenerator/StringBuilder.cpp
	JsonGenerator/StringBuilder.h
	JsonGeneratorTests/EscapedStringTests.cpp
	JsonGeneratorTests/Issue10.cpp
	JsonGeneratorTests/JsonArrayTests.cpp
	JsonGeneratorTests/JsonObject_Indexer_Tests.cpp
	JsonGeneratorTests/JsonObject_PrintTo_Tests.cpp
	JsonGeneratorTests/JsonValue_Cast_Tests.cpp
	JsonGeneratorTests/JsonValue_PrintTo_Tests.cpp
	JsonGeneratorTests/PrettyPrint_Array_Tests.cpp
	JsonGeneratorTests/PrettyPrint_Object_Tests.cpp
	JsonGeneratorTests/PrettyPrint_String_Tests.cpp
	JsonGeneratorTests/StringBuilderTests.cpp
	JsonParser.cpp
	JsonParser.h
	JsonParser/JsonArray.cpp
	JsonParser/JsonArray.h
	JsonParser/JsonArrayIterator.h
	JsonParser/JsonObject.cpp
	JsonParser/JsonObject.h
	JsonParser/JsonObjectIterator.h
	JsonParser/JsonPair.h
	JsonParser/JsonParser.h
	JsonParser/JsonParserBase.cpp
	JsonParser/JsonParserBase.h
	JsonParser/JsonToken.cpp
	JsonParser/JsonToken.h
	JsonParser/JsonValue.cpp
	JsonParser/JsonValue.h
	JsonParser/README.md
	JsonParserTests/GbathreeBug.cpp
	JsonParserTests/JsonArrayIteratorTests.cpp
	JsonParserTests/JsonArrayTests.cpp
	JsonParserTests/JsonObjectIteratorTests.cpp
	JsonParserTests/JsonObjectTests.cpp
	JsonParserTests/JsonStringTests.cpp
	JsonParserTests/TestHashGenerator.cpp
	README.md
	library.json
2014-11-29 14:30:23 +01:00
69f6967ad4 Merge branch '4.0' of github.com:bblanchon/ArduinoJson into 4.0 2014-11-29 14:09:29 +01:00
4e3f554b68 Made script executable on unix 2014-11-29 14:03:32 +01:00
79f6f0dd86 Minor changes in doc 2014-11-29 13:53:18 +01:00
02f6fab025 Minor changes in the docs 2014-11-29 10:36:15 +01:00
a61fc5b836 Minor corrections to the doc 2014-11-29 09:30:11 +01:00
f3a84857d9 Removed unused function 2014-11-22 18:54:40 +01:00
95eb16233c Added tests of JsonArray::invalid() and JsonObject::invalid() 2014-11-22 18:52:46 +01:00
33654a480b Added Build Status badge 2014-11-15 15:22:37 +01:00
c296f27640 Disabled threading in googletest 2014-11-15 15:09:48 +01:00
4f55f63a77 Improved Travis configuration 2014-11-15 15:02:48 +01:00
a66299a936 Replaced -Wpedantic by -pedantic 2014-11-15 14:58:29 +01:00
a2cbb68a40 Added missing argument to cmake 2014-11-15 14:46:00 +01:00
4163debdd9 Added Travis configuration file 2014-11-15 14:42:23 +01:00
c92ff81ddd Updated for v4.0 2014-11-11 18:34:13 +01:00
783add8357 Added Arduino 1.0.6 requirement 2014-11-11 18:34:04 +01:00
3b77dbbed7 Fixed warnings in Visual Studio 2014-11-11 18:18:26 +01:00
160ff0961e Added PlatformIO manifest file 2014-11-11 18:09:58 +01:00
06909c451f Added donation link 2014-11-11 17:50:40 +01:00
b7d8b45e5a Synchronized with master 2014-11-11 17:35:20 +01:00
88bfaac7e6 Changed expected output from "0.0" to "0.00" 2014-11-11 17:33:54 +01:00
3c51017e4a Added tests fo JsonVariant::printTo() 2014-11-11 17:26:51 +01:00
33f6376122 Fixed is<T>() 2014-11-11 17:26:13 +01:00
2beb87136b Fixed writeTo() of invalid and undefined value 2014-11-11 17:15:53 +01:00
f6f8a63b99 Added a header to simplify library usage 2014-11-11 16:56:02 +01:00
e0ce711eb4 Fixed cpplint warnings 2014-11-11 16:43:35 +01:00
0911d8d796 Fixed cpplint warnings 2014-11-11 16:41:45 +01:00
99e5ff78f3 Removed empty document 2014-11-11 15:17:20 +01:00
5236de1433 Added memory usage 2014-11-11 14:46:23 +01:00
0c9451fd5f Updated for v4.0 2014-11-11 14:26:57 +01:00
dfac1cf71a Updated for v4.0 2014-11-11 14:11:49 +01:00
1e20e6ef77 Renamed file 2014-11-11 14:11:40 +01:00
a7b366e74f Updated for v4.0 2014-11-11 14:05:54 +01:00
3cfd36a5ce Reduced size by 16 bytes by inlining indent() and unindent() 2014-11-09 16:10:30 +01:00
3919f07890 Reduced size by 22 bytes by removing writeEmptyArray() and writeEmptyObject() 2014-11-09 13:54:03 +01:00
12e374d0da Reduced size by 2 bytes 2014-11-08 21:37:02 +01:00
36ee4876c6 Reduced sze by 26 bytes by inlining getOrCreateNodeAt() 2014-11-08 21:32:30 +01:00
05db56760f Reduced size by 38 bytes by inlining addNode() 2014-11-08 21:22:03 +01:00
e94089ca56 Reduced size by 52 bytes by inlining createNode() 2014-11-08 21:16:47 +01:00
dc1d0ca698 Added #include <ListNode.hpp> 2014-11-08 21:16:14 +01:00
627d85ce23 Added #pragma once 2014-11-08 21:15:34 +01:00
f6133f2d36 Reduced size by 300 bytes by reusing the JsonPrettyPrint from v3 2014-11-08 19:40:07 +01:00
d8dbfe6e6d Reduced size by 706 bytes by removing virtual destructors. 2014-11-08 17:13:41 +01:00
1c450fd3aa Fixed floating point value parsing in the form "4e2" or "4E2". 2014-11-08 15:56:40 +01:00
2e47d546b2 Writing documentation... 2014-11-08 15:48:51 +01:00
01f13c1b11 Writing documentation... 2014-11-07 22:12:40 +01:00
9dc7c2a031 Writing documentation... 2014-11-07 21:41:42 +01:00
fe779dace4 Writing documentation... 2014-11-07 20:14:09 +01:00
6eef52cc9c Writing documentation... 2014-11-07 18:21:34 +01:00
d38131d495 Added JsonObject::containsKey() 2014-11-07 17:27:30 +01:00
b4b475d692 Simplified generator example 2014-11-07 16:23:21 +01:00
fe17706b6c Writing documentation... 2014-11-07 16:18:19 +01:00
d7bad3d70b Added flag -fno-exceptions 2014-11-07 13:31:55 +01:00
5a56ec0636 Renamed writeInteger to writeLong to be more consistent 2014-11-07 13:27:42 +01:00
35a95f00d9 Inlined the content of JsonWriter.cpp 2014-11-07 13:23:11 +01:00
93397880ca Fixed compilation error with old GCC version (like the one in Arduino 1.0.6) 2014-11-07 12:12:58 +01:00
8c4c3d8fda Fixed warning with GCC 2014-11-07 11:59:07 +01:00
49025d322f Fixed warning in GCC 2014-11-07 11:52:18 +01:00
9d2ee6ce63 Fixed creation of JsonVariant::_invalid 2014-11-07 11:45:28 +01:00
70aabca0f7 Remove diagnostic lines 2014-11-07 11:28:04 +01:00
dfd59f644b Added comments 2014-11-07 09:35:53 +01:00
ee520d1ff5 Cleaned parseArray() 2014-11-07 09:30:00 +01:00
ee580f1968 Removed comment line 2014-11-07 09:21:07 +01:00
5179aa0d4f Cleaned parseObject() 2014-11-07 09:20:48 +01:00
a7b78fadb0 Removed StaticJsonBuffer.clear() 2014-11-06 17:08:42 +01:00
d94bcbf249 Added comments 2014-11-06 16:58:24 +01:00
086e99efb4 Added comment 2014-11-06 16:29:29 +01:00
7b8aba46cc Fixed compilartion error 2014-11-06 16:08:15 +01:00
579c9359df Added comments 2014-11-06 16:08:06 +01:00
885e35e892 Added comments 2014-11-06 14:48:14 +01:00
e7864c9566 Use Print& instead of Print* 2014-11-06 14:29:29 +01:00
6e67bc442f Added comments 2014-11-06 14:27:14 +01:00
ac9b776aa1 Fixed remaining cpplint warnings 2014-11-06 14:08:53 +01:00
d8e595907b Muted runtime/references 2014-11-06 13:59:38 +01:00
1e02fabdec Simplified JsonWriter and PrettyJsonWriter 2014-11-06 13:52:33 +01:00
79bfe731af Added comments 2014-11-06 13:42:16 +01:00
a3425a6306 Added a nesting limit to the parser to prevent stack overflow that could be a security issue 2014-11-06 10:24:37 +01:00
2e4dd2d591 Updated warning flags 2014-11-06 09:44:09 +01:00
f360cc664c Added empty line at end of file 2014-11-06 09:28:28 +01:00
ce6f839153 Warnings level were not correct with Clang 2014-11-06 09:28:04 +01:00
01949f7da0 Added more tests of StaticJsonBuffer 2014-11-05 21:10:36 +01:00
08de76e2ba Simplified StaticJsonBuffer tests 2014-11-05 13:54:53 +01:00
cb97e1fa19 Added tests of StaticJsonBuffer 2014-11-05 13:45:30 +01:00
95e564bfb6 Added test of a failing JsonBuffer::createObject() 2014-11-05 13:31:31 +01:00
342b079133 Rename Node into ListNode 2014-11-05 13:14:15 +01:00
8138c64116 Renamed NodeIterator into ListIterator 2014-11-05 13:12:20 +01:00
64b4e15ce6 Added tests of JsonObject::const_iterator 2014-11-05 13:10:22 +01:00
e722fc50b1 Delete Printable interface because it's not used anymore 2014-11-05 12:51:22 +01:00
a9f4f611d4 Extracting a common base class for JsonArray and JsonObject... 2014-11-05 11:53:08 +01:00
0fb4fa8f86 Extracting a common base class for JsonArray and JsonObject... 2014-11-05 11:43:59 +01:00
7d73e63c78 Extracting a common base class for JsonArray and JsonObject... 2014-11-05 11:38:36 +01:00
ebb591ef28 Extracting a common base class for JsonArray and JsonObject... 2014-11-05 11:28:19 +01:00
31dea656d5 Splitted JsonIterator into NodeIterator and NodeConstIterator 2014-11-05 11:16:36 +01:00
768312e870 Merged JsonArrayNode and JsonObjectNode into a single template 2014-11-05 11:09:48 +01:00
5d0e326bfd Removed JsonPair constructor 2014-11-05 09:31:29 +01:00
8ac4346fd5 Replaced JsonObjectIterator and JsonObjectConstIterator by a template 2014-11-05 09:27:03 +01:00
bafec6f1a3 Unified JsonArrayNode and JsonObjectNode 2014-11-05 09:24:15 +01:00
c6d11294e4 Replaced JsonArrayIterator and JsonArrayConstIterator by a template 2014-11-05 09:04:26 +01:00
6ce2497879 Move JsonPrintable into Internals/ 2014-11-05 08:53:41 +01:00
782b178f4e Fixed warnings in Visual Studio 2014-11-04 19:53:13 +01:00
64529bb1a3 Added test of JsonVariant::invalid() 2014-11-04 13:10:25 +01:00
01dc0d6268 Added test of undefined JsonVariant 2014-11-04 13:07:14 +01:00
289b5333d6 Improved test printers 2014-11-04 13:06:47 +01:00
4a17e8c34b Minor changes 2014-11-04 10:38:33 +01:00
c4cda780d5 Added more tests of subscript operator 2014-11-04 10:33:09 +01:00
e5669577df Added JsonVariant::operator[](const char*) 2014-11-04 10:30:45 +01:00
97768ec176 Added JsonVariant::operator[](int) 2014-11-04 10:22:13 +01:00
e25eaed75a Cleaned #includes 2014-11-04 10:01:21 +01:00
09f6d059a7 Renamed JsonValue to JsonVariant 2014-11-04 09:51:25 +01:00
699292b058 Arduino example are now compiling 2014-11-03 21:29:55 +01:00
d9cc259df3 Added declaration for placement new because it was not available in Arduino 2014-11-03 21:29:19 +01:00
43ad37e7ce Now use relative paths in for #include 2014-11-03 18:35:22 +01:00
bb816037d6 Minor change 2014-11-03 18:29:52 +01:00
04cde11a04 Now use uint8_t to store decimal count 2014-11-03 18:28:24 +01:00
2f8fde6772 Added ReferenceType::operator!=() 2014-11-03 18:25:17 +01:00
f224408c07 Added tests of comparison operators 2014-11-03 18:23:39 +01:00
21e073a3b4 Renamed JsonValueTests into JsonValue_Copy_Tests 2014-11-03 17:52:30 +01:00
f9ea82a2af Added many tests storing values in JsonValue 2014-11-03 17:50:01 +01:00
1ce6d663af Replaced 0 literals by more explicit '\0' and NULL 2014-11-03 17:03:55 +01:00
c1c63067d4 Removed old source files 2014-11-03 16:45:06 +01:00
a8d3e9997e Ported test of Gbathree's bug 2014-11-03 14:38:46 +01:00
7cdf7b1769 Added equality operator 2014-11-03 14:37:50 +01:00
429d5011b4 Made it possible to use const JsonObject& 2014-11-03 14:33:33 +01:00
54f9bd9572 Simplified JsonWriter hierarchy 2014-11-03 12:58:52 +01:00
2a60c96baf Removed virtuals from JsonWriter hierarchy 2014-11-03 12:51:24 +01:00
f26f4263ea Removing virtual methods... 2014-11-03 12:32:47 +01:00
507f809da0 Merge branch 'merge-parser-and-generator' of github.com:bblanchon/ArduinoJson into merge-parser-and-generator 2014-11-03 11:46:49 +01:00
ad83820257 Added integration test with YQL data 2014-11-01 16:39:51 +01:00
cd773e3f37 Added an integration test that uses prettyPrintTo() 2014-11-01 13:45:07 +01:00
9da7dce310 Fixed double formatting issue 2014-11-01 13:30:37 +01:00
825ab0357e Added integration test with a JSON sample from OpenWeatherMap 2014-11-01 09:09:58 +01:00
fead9b50b1 Fixed bug in parser when "null", "true" or "false" is mispelled 2014-10-31 21:08:04 +01:00
98463ea168 Added a script to run tests continuously 2014-10-31 18:41:34 +01:00
74b4544560 Fixed parsing when opening brace/bracket is missing 2014-10-31 16:50:21 +01:00
2b5b8fb4c5 Removed empty files 2014-10-31 16:30:10 +01:00
d35b680481 Removed ForwardDeclarations.hpp 2014-10-31 12:27:33 +01:00
ca0fbf00f9 Cleaning up... 2014-10-31 12:16:32 +01:00
5443e90baf Cleaning up... 2014-10-31 12:02:15 +01:00
a5dbb397ca Fixed failing test with clang 2014-10-31 11:38:58 +01:00
889f059758 All tests passed! 2014-10-30 21:51:59 +01:00
45a8ed6531 Huge refactoring in progress... 2014-10-30 15:31:27 +01:00
4c204840e9 Huge refactoring in progress... 2014-10-30 14:03:33 +01:00
c3001e9ea9 Huge refactoring in progress... 2014-10-30 10:49:02 +01:00
5cf744dbac Huge refactoring in progress... 2014-10-29 21:18:27 +01:00
ba2b142c8a Huge refactoring in progress... 2014-10-29 14:24:34 +01:00
10ab95522d Epic refactoring in progress 2014-10-28 17:58:46 +01:00
61218f12fd Epic refactoring in progress... 2014-10-28 16:29:55 +01:00
852256c1af Epic refactoring int progress... 2014-10-27 22:50:50 +01:00
8988cb4761 Epic refactoring in progress... 2014-10-27 14:03:44 +01:00
e0980292ef Epic refactoring in progress 2014-10-26 21:18:09 +01:00
cdf3777aa8 Removed unused friend 2014-10-25 21:02:56 +02:00
618a54579f Simplified JsonArray 2014-10-25 21:02:13 +02:00
9f69fabe20 Cleaned JsonNodeWrapper 2014-10-25 16:11:04 +02:00
e748ce32bc Removed all friends of JsonValue 2014-10-25 15:55:58 +02:00
fdeedabfd7 Fixed warning in Visual Studio 2014-10-24 19:59:14 +02:00
582216e004 Merged JsonArrayIterator and JsonObjectIterator into a one template class 2014-10-24 18:53:03 +02:00
1f6cd8e56e Removed usages of JsonNodeIterator 2014-10-24 18:31:50 +02:00
68fb03577c Moved forward declarations in a single .hpp file 2014-10-24 16:29:51 +02:00
bbef8931a6 Improved JsonArrayIterator 2014-10-24 16:12:05 +02:00
8071434515 Fixed many cpplint warnings 2014-10-24 00:08:25 +02:00
7f22a1ab39 Muted a few cpplint warnings 2014-10-23 23:59:05 +02:00
55b0eab3e6 Added newline at ed of file 2014-10-23 23:45:36 +02:00
e85f27c0f3 Added file headers with copyrights 2014-10-23 23:39:22 +02:00
e3b4f5038d Fixed path of test exe 2014-10-23 23:22:26 +02:00
b43da1e421 Switched to Google coding style to match cpplint expectations 2014-10-23 23:13:13 +02:00
5c8283b3e4 Added cpplint 2014-10-23 23:10:22 +02:00
3dc533fca0 Merge pull request #30 from ivankravets/patch-2
Avoid trademark issues with library name
2014-10-23 22:29:42 +02:00
d38cbd374a Avoid trademark issues with library name
Added frameworks and platforms fields
Updated Library Registry: http://platformio.ikravets.com/#!/lib/show/64/Json
2014-10-23 22:27:22 +03:00
9175046f35 Formated code with clang-format 2014-10-23 19:54:00 +02:00
888fdc1d54 Improved JsonObjectIterator 2014-10-23 18:56:04 +02:00
d83f1a6319 Added .hpp files 2014-10-23 18:22:50 +02:00
ff5f3f3a2c Merge branch 'merge-parser-and-generator' of github.com:bblanchon/ArduinoJson into merge-parser-and-generator
Conflicts:
	test/JsonObject_Iterator_Tests.cpp
2014-10-23 17:43:40 +02:00
e4779512e6 Added JsonValue::as<T>() 2014-10-23 17:22:23 +02:00
8947a6c9de Added more tests 2014-10-23 17:01:24 +02:00
fa805b4998 Test parsing of nested objects 2014-10-23 12:15:46 +02:00
451c0ee70d Added JsonObjectIterator::operator->() 2014-10-22 23:32:25 +02:00
40ac60b941 Added JsonObjectIterator 2014-10-22 21:56:38 +02:00
7e98d136f4 Added more warning flags for GCC (as suggested in issue #28) 2014-10-22 21:25:19 +02:00
c800948342 Fixed warning in GCC 2014-10-22 20:51:29 +02:00
7fbc3cb6a6 Fixed warnings in Visual Studio 2014-10-22 20:48:20 +02:00
d842e246c9 Added JsonArrayIterator 2014-10-22 17:59:59 +02:00
9946abf731 Added more tests 2014-10-22 16:04:29 +02:00
1e0464f5b4 Fixed negative number parsing 2014-10-22 15:57:50 +02:00
5aefc7d652 Simplified the parser 2014-10-22 12:25:41 +02:00
743381de6d Added 3 tests 2014-10-22 11:56:40 +02:00
d70ff26164 Remove support of unquoted keys 2014-10-22 11:54:33 +02:00
316d036785 More test on object parsing 2014-10-22 10:55:36 +02:00
c82e6d747b Test with spaces in objects 2014-10-21 23:42:26 +02:00
04330a7a47 Parse key value pairs 2014-10-21 23:40:04 +02:00
cfbe50057a Test with a missing closing brace 2014-10-21 21:50:00 +02:00
9c1b6b80aa Parse empty object 2014-10-21 21:11:30 +02:00
0daf82eee2 Renamed all .h files into .hpp (so that Sublime Text selects C++ syntax) 2014-10-19 15:46:36 +02:00
074c39ca5b Fixed namespaces 2014-10-18 23:05:54 +02:00
1abb8ac6ae Added tests of the trailing string 2014-10-18 22:25:48 +02:00
b19a37538c Changed JsonParser_String_Tests into QuotedString_ExtractFrom_Tests 2014-10-18 22:12:43 +02:00
fc4faacfec Renamed EscapedString into QuotedString 2014-10-18 22:04:13 +02:00
bbc2aa4f2a Allow string to be enclosed in single quotes 2014-10-18 21:54:32 +02:00
1f6bd5c04d Added more test of escaped chars 2014-10-17 22:32:55 +02:00
32ffb75394 Fixed compilation warning 2014-10-17 21:51:58 +02:00
7df73824aa Fixed field orders 2014-10-17 20:57:38 +02:00
9c32ae2300 Parser: unescape strings 2014-10-17 20:52:27 +02:00
b15dac7edf Renamed EscapedStringTests into EscapedString_PrintTo_Tests 2014-10-17 12:53:38 +02:00
2a62132bf0 Added JsonParser_String_Tests.cpp 2014-10-16 22:13:31 +02:00
a0a82c0f4e Renamed file 2014-10-16 21:43:44 +02:00
24b46af48a Moved build output to bin/ and lib/ 2014-10-16 21:29:59 +02:00
fed79bfd81 Updated the script to work on Windows too 2014-10-16 21:06:13 +02:00
7dbaac1070 Added a new script to create build environments 2014-10-16 18:23:41 +02:00
58d2c4a62f Renamed srcs/ into src/ 2014-10-16 16:25:42 +02:00
b847576bb4 Renamed tests/ into test/ 2014-10-16 16:23:24 +02:00
58f155e135 Moved .h files to include/ 2014-10-16 00:11:23 +02:00
241ca79114 Parse simple strings 2014-10-15 23:39:25 +02:00
3d92531ad3 Parse 'null' 2014-10-15 23:27:38 +02:00
c61ee09d26 Parse booleans 2014-10-15 23:10:52 +02:00
c59ddd8a9d Fixed number of tokens (issue #29) 2014-10-15 16:31:20 +02:00
086d07151f Parse doubles 2014-10-15 14:54:31 +02:00
a1cb9c9399 Added methods to clarify the tests 2014-10-15 13:51:20 +02:00
f265b6ed11 Fixed compilation warnings 2014-10-14 21:57:34 +02:00
5db34580f2 Added test for spaces in arrays 2014-10-14 21:50:51 +02:00
beb49a9446 Parse an array with two longs 2014-10-14 21:48:22 +02:00
ee205971e9 Test what happens with just an opening bracket 2014-10-14 21:35:47 +02:00
ded6364e1d Moved the location of the VS files 2014-10-14 21:24:40 +02:00
5b6b38564f Parse long values 2014-10-14 21:24:26 +02:00
31c1a3d804 Added a script to create Sublime Text project 2014-10-14 18:02:24 +02:00
81f3460806 Parse empty array with leading spaces 2014-10-14 18:01:49 +02:00
081b345e7c Parse invalid array 2014-10-14 17:28:57 +02:00
f468db6757 Parse empty array 2014-10-14 17:16:21 +02:00
c7dcf864cc Added *.h files 2014-10-14 13:55:07 +02:00
6d39bfa703 Added a script to generate VS solution 2014-10-14 12:31:08 +02:00
4ee1ac015f Created scripts/ 2014-10-14 12:23:40 +02:00
b2e2556ef6 Removed Visual Studio project files 2014-10-14 12:22:17 +02:00
8f74e4e44e Splitted CMakeLists.txt 2014-10-14 11:01:50 +02:00
be891daa5a Added CMakeLists.txt 2014-10-14 09:52:04 +02:00
95a2d6714e Fix minor issues for GCC 2014-10-14 09:50:58 +02:00
3ce5e53323 Removed duplicate code of v3 2014-10-13 21:27:56 +02:00
f8c3cdf2ff Fixed mistakes in the tests 2014-10-13 21:03:32 +02:00
88aed98447 Fixed JsonContainer::operator== 2014-10-13 21:01:11 +02:00
3ae90b66c6 Added tested for createNestedArray() and createNestedObject() 2014-10-13 18:12:23 +02:00
10c0a8ba70 Ported tests of issue #10 2014-10-13 17:56:16 +02:00
d192a14e2e Fixed compiler warning 2014-10-11 16:59:16 +02:00
b49aa22c65 Replaced non-const references by pointer to follow Google style guide 2014-10-11 16:58:24 +02:00
dae0dc5ebb Replaced old style casts (issue #28) 2014-10-10 18:44:04 +02:00
35eaa55b3a Added JSON_PROXY to copy arrays and objects by reference 2014-10-09 18:20:40 +02:00
bf2d726746 Minor changes 2014-10-09 14:48:55 +02:00
0dce0022d3 Made JsonNodeType private 2014-10-09 14:31:25 +02:00
1bff34a204 Made JsonNode::next private 2014-10-09 14:19:43 +02:00
24c60619d5 Made JsonNode::type private 2014-10-09 14:17:09 +02:00
b0e12e8852 Refactoring JsonNode... 2014-10-09 12:14:10 +02:00
f7fa9e9467 Added JsonArray::createNestedObject() 2014-10-07 15:27:24 +02:00
09b6f71853 Added JsonObject::createNestedArray() 2014-10-07 12:11:10 +02:00
e28119f03b Test JsonObject::prettyPrintTo() 2014-10-07 11:58:59 +02:00
7a40711af3 Added JsonContainer::prettyPrintTo() 2014-10-07 11:22:10 +02:00
b6799dc231 Refactored the serialization 2014-10-05 16:26:13 +02:00
31c9ea9b28 Test JsonArray serialization 2014-10-05 15:23:52 +02:00
6330ab1271 Test that JsonObject can contain inner arrays 2014-10-05 15:15:25 +02:00
c35a0fadc3 Test that JsonArray can contain inner objects 2014-10-05 15:14:29 +02:00
bbe034222c Test that JsonArray can contain inner arrays 2014-10-05 15:13:00 +02:00
305944e907 Test that JsonArray can store strings 2014-10-05 15:04:44 +02:00
f0754aed53 Test that JsonArray can store booleans 2014-10-05 15:04:17 +02:00
99a785179d Test that JsonArray can contain doubles 2014-10-05 15:02:40 +02:00
21259bc61a Test that JsonArray can store integers 2014-10-05 14:55:14 +02:00
4c67d0579a Test that JsonArray grows after calling add() 2014-10-05 14:48:19 +02:00
cb3c59ec07 Added JsonArray 2014-10-05 14:40:03 +02:00
e725b756a6 Merge pull request #27 from ivankravets/patch-1
PlatformIO-based manifest file
2014-10-04 10:31:15 +02:00
dbe6f89ed8 PlatformIO-based manifest file
Web: http://platformio.ikravets.com/#!/lib/show/Arduino-Json
Docs: http://docs.platformio.ikravets.com/en/latest/librarymanager/index.html
2014-10-03 22:06:24 +03:00
84e34d2a27 Added content of issue #26 in the testimonials 2014-10-03 10:06:52 +02:00
4d2d535a03 Pulled up code from JsonObject to JsonContainer 2014-10-01 16:56:22 +02:00
b0e43f7538 Extracted class JsonContainer 2014-10-01 16:18:14 +02:00
d66a7adc22 Moved files into Internals/ and Arduino/ 2014-10-01 16:08:32 +02:00
1a98fd5dfc Serialize inner objects 2014-10-01 15:47:32 +02:00
57400cee14 Extracted methods serializeObject and serializeKeyValue 2014-10-01 12:46:41 +02:00
c99bdbf4b9 Extracted JsonNodeSerializer 2014-10-01 12:28:30 +02:00
a665fa1dec Converted StringBuilder tests to gtest 2014-09-30 18:07:08 +02:00
78048d1d92 Converted EscapedString tests to gtest 2014-09-30 18:03:17 +02:00
065fe57a7c Serialize booleans in objects 2014-09-30 17:56:28 +02:00
f251563af1 Serialize floats in objects 2014-09-30 17:32:45 +02:00
c1ab55f9d9 Serialize integer values in object 2014-09-30 17:24:14 +02:00
27a4d57f7c Test that now value can be added when all nodes are allocated 2014-09-30 17:14:59 +02:00
22e36bbe9c Restored tests from previous test suite 2014-09-30 17:08:59 +02:00
d2e1b241be Test that size doesn't change when remove() is called with an invalid key 2014-09-30 17:07:29 +02:00
3d9e40a3a8 Test that the size is decreased when object are removed 2014-09-30 17:05:33 +02:00
9f85368cce Test serialization of an object with strings 2014-09-30 16:59:44 +02:00
3243f2dc58 Implement Printable 2014-09-30 16:43:25 +02:00
6b2705769a Refactored to use StringBuilder 2014-09-30 16:40:00 +02:00
ab2587f089 Test empty object serialization 2014-09-30 16:31:22 +02:00
d3cf568d07 Test that char* are copied 2014-09-28 21:35:08 +02:00
e417c137fc Test that bool values are copied 2014-09-28 21:23:40 +02:00
d549070fd3 Test that doubles in JsonValue are copied 2014-09-28 21:22:20 +02:00
42ce5ab31f Test that integers in JsonValue are copied 2014-09-28 21:18:43 +02:00
e190b20ae1 Fixed inner object bug 2014-09-28 21:04:59 +02:00
ce788d96c4 Changed naming convention to avoid shadowing (issue #25) 2014-09-28 13:36:41 +02:00
cc19266470 Added missing newline at end-of-file (issue #24) 2014-09-27 21:24:29 +02:00
18f93b4eb6 Fixed issue #22 2014-09-27 21:02:43 +02:00
e682ed5a1e Added a test prooving issue #22 2014-09-27 21:02:43 +02:00
bc44c36385 Test that nested JsonObject can be stored 2014-09-27 16:18:40 +02:00
bcc8cece24 Moved JsonObject._buffer into the JsonNode's content 2014-09-27 15:34:34 +02:00
a7ff04db0e Added "const" to cast operators 2014-09-27 15:25:00 +02:00
a9a51ec1e2 Test that string can be stored in JsonObject 2014-09-27 15:24:16 +02:00
0495297c6c Group test in a test fixture 2014-09-27 15:19:03 +02:00
75588946c6 Test that boolean values can be stored in a JsonObject 2014-09-27 15:04:06 +02:00
5fa446d3f5 Test that a double can be stored in a JsonObject 2014-09-27 14:59:02 +02:00
71fd2de675 Test that integers can be stored in a JsonObject 2014-09-27 14:51:50 +02:00
a2fc188526 Test that adding the same value twice doesn't increase the size of the object 2014-09-27 14:43:19 +02:00
166bdd6919 Test that adding values to the JsonObject increase the size of the buffer 2014-09-27 12:16:53 +02:00
4d4119e589 Test that JsonObject.size() is increased when values are added 2014-09-27 11:53:26 +02:00
91649df593 Test that CreateObject() returns an empty JsonObject 2014-09-27 11:42:27 +02:00
890e811e80 Test that size can't go above capacity 2014-09-27 11:33:45 +02:00
bb887f94e7 Test size() after calling CreateObject 2014-09-27 10:16:30 +02:00
6e45f7c790 Test initial size of StaticJsonB 2014-09-27 09:58:34 +02:00
5580adb4a6 Added first test on StaticJsonBuffer 2014-09-27 09:56:53 +02:00
60a5d72367 Started a new solution from scratch.
Added Google test
2014-09-24 11:41:19 +02:00
4cfb0ab84d Fixed issue #21 2014-09-20 18:56:22 +02:00
a1b6c2df75 Merge branch 'parse-escaped-chars' 2014-09-09 21:33:12 +02:00
feb6060887 Updated change-log 2014-09-09 21:32:27 +02:00
49d2b4b2a2 Updated code size 2014-09-09 21:25:25 +02:00
286a514fbe Minor clean up 2014-09-09 21:23:37 +02:00
9d3b522e7b Reduced code size (-6 bytes) 2014-09-07 20:11:33 +02:00
c32642e130 Reduced code size (-6 bytes) 2014-09-07 19:55:54 +02:00
7a3fa35bd8 Added LICENSE.md 2014-09-06 12:04:09 +02:00
0154fc15cb Added escaped char replacement 2014-09-04 21:49:43 +02:00
24d173c3b9 Added tests of escaped chars 2014-09-04 21:30:50 +02:00
d4c1b6f2c2 Extracted a class to test strings 2014-09-04 21:20:40 +02:00
58c051f564 Added comments 2014-09-01 21:36:09 +02:00
763aa7fe37 Added an overload of prettyPrintTo() 2014-09-01 21:22:56 +02:00
cd88fb0882 Added prettyPrintTo() 2014-09-01 21:22:34 +02:00
ec843659d8 Updated CHANGELOG.md 2014-09-01 21:14:09 +02:00
2997a405a0 Added IndentedPrint example 2014-08-26 12:48:59 +02:00
57f28c2017 Reduced code size 2014-08-26 12:11:17 +02:00
b3b70b78cf Fixed build error in Arduino IDE 2014-08-26 12:03:50 +02:00
48018bd6e6 Set default tab size to 2 2014-08-26 11:59:41 +02:00
61952a9bcd Added setTabSize() 2014-08-26 11:58:33 +02:00
602cc104f9 Set line ending to CR LF, like in Arduino source code 2014-08-26 11:52:12 +02:00
d71a39211d Fixed prettyPrintTo calling printTo 2014-08-26 10:26:40 +02:00
f77a8b02e3 Fixed file names 2014-08-26 10:26:12 +02:00
aa2cd0db00 Moved IndentedPrint into the namespace ArduinoJson::Generator 2014-08-26 10:16:13 +02:00
f127ef6019 Refactoring... 2014-08-26 10:13:49 +02:00
3ae7327687 Renamed PrettyPrintDecorator into JsonPrettyPrint 2014-08-26 10:08:54 +02:00
23e61cc0f7 Renamed IndentedPrintDecorator into IndentedPrint 2014-08-26 09:56:05 +02:00
b5002265cf Refactoring... 2014-08-26 09:53:32 +02:00
e48ea94789 Refactoring... 2014-08-26 09:49:59 +02:00
6539c6982c Extracted class IndentedPrintDecorator from PrettyPrintDecorator 2014-08-26 09:28:41 +02:00
d877d77b63 Moved PrettyPrintDecorator into the namespace ArduinoJson::Generator 2014-08-25 13:19:07 +02:00
1df6cde026 Refactoring... 2014-08-25 13:14:09 +02:00
fafae8181b Refactoring... 2014-08-25 12:51:56 +02:00
151fc52c1c Refactoring... 2014-08-25 12:48:38 +02:00
ea79340dc7 Refactoring... 2014-08-25 12:41:49 +02:00
9e88514700 Refactoring.... 2014-08-25 12:28:58 +02:00
752378a8cb Fixed bug when a string contains a brace 2014-08-25 12:23:08 +02:00
8465cc0c83 Refactoring... 2014-08-25 11:46:42 +02:00
2ddf8f1619 Renamed IndentedPrintDecorator to PrettyPrintDecorator 2014-08-25 11:42:07 +02:00
f7aa0f89e3 Added JsonPrintable.prettyPrintTo(Print&) 2014-08-25 11:39:04 +02:00
3d322fdb28 Test nested arrays 2014-08-25 11:02:38 +02:00
981adf1989 Test empty nested arrays 2014-08-25 11:01:22 +02:00
dbc3bee3a0 Test array with 2 elements 2014-08-25 10:55:48 +02:00
3f2b7b706a Test an array with one element 2014-08-25 10:55:09 +02:00
c243417585 Test nested objects 2014-08-25 10:46:43 +02:00
514a6c0879 Splitted the indentation tests into 3 files 2014-08-25 10:42:00 +02:00
76f9ecce75 Tests empty nested objects in objects 2014-08-25 10:36:25 +02:00
410ca55e88 Added a space before the object's values 2014-08-25 10:34:28 +02:00
66c05041e8 Test an object with comma, quote and column in the value 2014-08-25 10:31:03 +02:00
aafabd8e8d Test an object with two memebrs 2014-08-25 10:22:42 +02:00
eb1a774778 Fixed empty object output 2014-08-25 09:56:51 +02:00
75c89e7b35 Test an object with one member 2014-08-25 09:52:42 +02:00
e31a2136fc Test with an empty array 2014-08-25 09:24:31 +02:00
380722402f Added a test of an empty object 2014-08-25 09:23:41 +02:00
030c8542e7 Now also test the return value 2014-08-25 09:19:26 +02:00
1f25d4434e Added test of an empty string 2014-08-25 09:17:32 +02:00
f29904e217 Added skeleton of class IndentedPrintDecorator 2014-08-25 09:06:46 +02:00
7246db7691 Added a note to avoid issue #10 2014-08-04 15:12:09 +02:00
4bdbc6c1fc Updated CHANGELOG.md 2014-08-04 14:59:09 +02:00
8e6fdb20eb Added tag in filename 2014-08-04 14:56:19 +02:00
016d0d699e Added a script to create Arduino package 2014-08-04 14:47:32 +02:00
6771603a05 Simplified JsonArray tests 2014-08-04 12:18:17 +02:00
d067cf0e84 Fixed tests 2014-08-04 09:35:57 +02:00
13593d73a3 Fixed nested object in arrays bug 2014-08-04 09:30:57 +02:00
bc86ae800a Changed JsonArray tests to show the issue 2014-08-04 09:22:45 +02:00
df52dceaa1 Added tests for issue #10 2014-08-04 09:21:04 +02:00
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
322 changed files with 150261 additions and 3704 deletions

11
.gitignore vendored
View File

@ -1,6 +1,5 @@
*.sdf
*.user
*.suo
Debug
ipch
*.opensdf
.DS_Store
/.idea
/build
/bin
/lib

6
.travis.yml Normal file
View File

@ -0,0 +1,6 @@
language: c++
compiler:
- gcc
- clang
before_script: cmake .
script: make && make test

View File

@ -1,28 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonGeneratorTests", "JsonGeneratorTests\JsonGeneratorTests.vcxproj", "{B9545D97-E084-4A19-8E48-929157064360}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JsonParserTests", "JsonParserTests\JsonParserTests.vcxproj", "{4DD596EF-0185-4AB4-A3C2-F20C496F7806}"
EndProject
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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -1,6 +1,84 @@
Arduino JSON: change log
========================
v4.0
----
* Unified parser and generator API (issue #23)
* Updated library layout, now requires Arduino 1.0.6 or newer
**BREAKING CHANGE**: API changed significantly, see `doc/Migrating to the new API.md`.
v3.4
----
* Fixed escaped char parsing (issue #16)
v3.3
----
* Added indented output for the JSON generator (issue #11), see example bellow.
* Added `IndentedPrint`, a decorator for `Print` to allow indented output
Example:
JsonOject<2> json;
json["key"] = "value";
json.prettyPrintTo(Serial);
v3.2
----
* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1).
v3.1
----
* Calling `Generator::JsonObject::add()` twice with the same `key` now replaces the `value`
* Added `Generator::JsonObject::operator[]`, see bellow the new API
* Added `Generator::JsonObject::remove()` (issue #9)
Old generator API:
JsonObject<3> root;
root.add("sensor", "gps");
root.add("time", 1351824120);
root.add("data", array);
New generator API:
JsonObject<3> root;
root["sensor"] = "gps";
root["time"] = 1351824120;
root["data"] = array;
v3.0
----
* New parser API, see bellow
* Renamed `JsonHashTable` into `JsonObject`
* Added iterators for `JsonArray` and `JsonObject` (issue #4)
Old parser API:
JsonHashTable root = parser.parseHashTable(json);
char* sensor = root.getString("sensor");
long time = root.getLong("time");
double latitude = root.getArray("data").getDouble(0);
double longitude = root.getArray("data").getDouble(1);
New parser API:
JsonObject root = parser.parse(json);
char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
v2.1
----

15
CMakeLists.txt Normal file
View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 2.8.4)
project(ArduinoJson)
enable_testing()
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -W4)
endif()
add_subdirectory(src)
add_subdirectory(test)

View File

@ -1,12 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014 - MIT License
*/
// This file is here to help the Arduino IDE find the .cpp files
#include "JsonGenerator/EscapedString.cpp"
#include "JsonGenerator/JsonArrayBase.cpp"
#include "JsonGenerator/JsonValue.cpp"
#include "JsonGenerator/JsonHashTableBase.cpp"
#include "JsonGenerator/StringBuilder.cpp"

View File

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

View File

@ -1,47 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "EscapedString.h"
using namespace ArduinoJson::Internals;
static inline char getSpecialChar(char c)
{
// Optimized for code size on a 8-bit AVR
const char* p = "\"\"\\\\\bb\ff\nn\rr\tt\0";
while (p[0] && p[0] != c)
{
p += 2;
}
return p[1];
}
static inline size_t printCharTo(char c, Print& p)
{
char specialChar = getSpecialChar(c);
return specialChar != 0
? p.write('\\') + p.write(specialChar)
: p.write(c);
}
size_t EscapedString::printTo(Print& p) const
{
const char* s = rawString;
if (!s) return p.print("null");
size_t n = p.write('\"');
while (*s)
{
n += printCharTo(*s++, p);
}
return n + p.write('\"');
}

View File

@ -1,29 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "Print.h"
namespace ArduinoJson
{
namespace Internals
{
class EscapedString
{
public:
void set(const char* s)
{
rawString = s;
}
size_t printTo(Print&) const;
private:
const char* rawString;
};
}
}

View File

@ -1,28 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonArrayBase.h"
namespace ArduinoJson
{
namespace Generator
{
template<int N>
class JsonArray : public JsonArrayBase
{
public:
JsonArray()
: JsonArrayBase(items, N)
{
}
private:
Internals::JsonValue items[N];
};
}
}

View File

@ -1,34 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonArrayBase.h"
using namespace ArduinoJson::Generator;
using namespace ArduinoJson::Internals;
size_t JsonArrayBase::printTo(Print& p) const
{
size_t n = 0;
n += p.write('[');
// NB: the code has been optimized for a small size on a 8-bit AVR
const JsonValue* current = items;
for (int i = count; i > 0; i--)
{
n += current->printTo(p);
current++;
if (i > 1)
{
n += p.write(',');
}
}
n += p.write(']');
return n;
}

View File

@ -1,49 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonObjectBase.h"
namespace ArduinoJson
{
namespace Generator
{
class JsonArrayBase : public JsonObjectBase
{
public:
JsonArrayBase(Internals::JsonValue* items, int capacity)
: items(items), capacity(capacity), count(0)
{
}
template<typename T>
void add(T value)
{
if (count >= capacity) return;
items[count++].set(value);
}
template<int DIGITS>
void add(double value)
{
if (count >= capacity) return;
Internals::JsonValue& v = items[count++];
v.set<DIGITS>(value);
}
virtual size_t printTo(Print& p) const;
using JsonObjectBase::printTo;
private:
Internals::JsonValue* items;
int capacity, count;
};
}
}

View File

@ -1,27 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonHashTableBase.h"
namespace ArduinoJson
{
namespace Generator
{
template<int N>
class JsonHashTable : public JsonHashTableBase
{
public:
JsonHashTable()
: JsonHashTableBase(items, N)
{
}
private:
KeyValuePair items[N];
};
}
}

View File

@ -1,36 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonHashTable.h"
using namespace ArduinoJson::Generator;
size_t JsonHashTableBase::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 += current->key.printTo(p);
n += p.write(':');
n += current->value.printTo(p);
current++;
if (i > 1)
{
n += p.write(',');
}
}
n += p.write('}');
return n;
}

View File

@ -1,61 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonObjectBase.h"
#include "EscapedString.h"
namespace ArduinoJson
{
namespace Generator
{
class JsonHashTableBase : public JsonObjectBase
{
public:
template<typename T>
void add(const char* key, T value)
{
if (count >= capacity) return;
items[count].key.set(key);
items[count].value.set(value);
count++;
}
template<int DIGITS>
void add(const char* key, double value)
{
if (count >= capacity) return;
items[count].key.set(key);
items[count].value.set<DIGITS>(value);
count++;
}
using JsonObjectBase::printTo;
virtual size_t printTo(Print& p) const;
protected:
struct KeyValuePair
{
Internals::EscapedString key;
Internals::JsonValue value;
};
JsonHashTableBase(KeyValuePair* items, int capacity)
: items(items), capacity(capacity), count(0)
{
}
private:
KeyValuePair* items;
int capacity, count;
};
}
}

View File

@ -1,31 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonValue.h"
#include "Print.h"
#include "Printable.h"
namespace ArduinoJson
{
namespace Generator
{
class JsonObjectBase : 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

@ -1,32 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "EscapedString.h"
#include "JsonValue.h"
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 c.asString.printTo(p);
}

View File

@ -1,94 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "EscapedString.h"
#include "Printable.h"
#include "StringBuilder.h"
namespace ArduinoJson
{
namespace Internals
{
class JsonValue
{
public:
void set(bool value)
{
printToImpl = &printBoolTo;
content.asBool = value;
}
void set(long value)
{
printToImpl = &printLongTo;
content.asLong = value;
}
void set(int value)
{
printToImpl = &printLongTo;
content.asLong = value;
}
void set(Printable& value)
{
printToImpl = &printPrintableTo;
content.asPrintable = &value;
}
void set(const char* value)
{
printToImpl = &printStringTo;
content.asString.set(value);
}
void set(double value)
{
set<2>(value);
}
template<int DIGITS>
void set(double value)
{
printToImpl = &printDoubleTo<DIGITS>;
content.asDouble = value;
}
size_t printTo(Print& p) const
{
// handmade polymorphism
return printToImpl(content, p);
}
private:
union Content
{
bool asBool;
long asLong;
Printable* asPrintable;
EscapedString asString;
double asDouble;
};
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);
}
};
}
}

View File

@ -1,28 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#ifndef ARDUINO
typedef unsigned char uint8_t;
// This class reproduces Arduino's Print
class Print
{
public:
virtual size_t write(uint8_t) = 0;
size_t print(const char[]);
size_t print(double, int = 2);
size_t print(long);
};
#else
#include <Print.h>
#endif

View File

@ -1,24 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#ifndef ARDUINO
class Print;
class Printable
{
public:
virtual size_t printTo(Print& p) const = 0;
};
#else
#include <Printable.h>
#endif

View File

@ -1,167 +0,0 @@
Arduino JSON library - Generator
================================
This library is a simple JSON encoder 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 in any other C++ project.
Features
--------
* Supports nested objects
* Elegant API, very easy to use
* Fixed memory allocation (no malloc)
* Small footprint
* Implements Arduino's Printable interface
* MIT License
Example
-------
JsonArray<2> array;
array.add<6>(48.756080);
array.add<6>(2.302038);
JsonHashTable<3> root;
root.add("sensor", "gps");
root.add("time", 1351824120);
root.add("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;
### 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 an array or an hash-table.
#### 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 the 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
JsonHashTable<8> nestedHash;
array.add(nestedHash);
#### Hash-table
You create a hash-table with the following line:
JsonHashTable<8> hash;
Like with the array class, there is a template parameter that gives the capacity of the hash-table.
Then you can add strings, integer, booleans, etc:
hash.add("key1", "bazinga!");
hash.add("key2", 42);
hash.add("key3", true);
As for the arrays, there are two syntaxes for the floating point values:
array.add<4>("key4", 3.1415); // 4 digits: "3.1415"
array.add("key5", 3.14); // 2 digits: "3.14"
Finally you can add nested objects:
JsonArray<8> nestedArray;
hash.add("key6", nestedArray);
or
JsonHashTable<8> nestedHash;
hash.add("key7", nestedHash);
### 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 `JsonHashTable`, 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 `JsonHashTable` 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 |
| JsonHashTable&lt;N&gt; | 8 + 8 x N |

View File

@ -1,17 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "StringBuilder.h"
using namespace ArduinoJson::Internals;
size_t StringBuilder::write(uint8_t c)
{
if (length >= capacity) return 0;
buffer[length++] = c;
buffer[length] = 0;
return 1;
}

View File

@ -1,31 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "Print.h"
namespace ArduinoJson
{
namespace Internals
{
class StringBuilder : public Print
{
public:
StringBuilder(char* buf, int size)
: buffer(buf), capacity(size - 1), length(0)
{
buffer[0] = 0;
}
virtual size_t write(uint8_t c);
private:
char* buffer;
int capacity;
int length;
};
}
}

View File

@ -1,97 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "EscapedString.h"
#include "StringBuilder.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Internals;
namespace JsonGeneratorTests
{
TEST_CLASS(EscapedStringTests)
{
char buffer[1024];
size_t returnValue;
EscapedString escapedString;
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));
escapedString.set(input);
returnValue = escapedString.printTo(sb);
}
void outputMustBe(const char* expected)
{
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), returnValue);
}
};
}

View File

@ -1,173 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonArray.h"
#include "JsonHashTable.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(JsonObjectBase& value)
{
arr.add<JsonObjectBase&>(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

@ -1,114 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B9545D97-E084-4A19-8E48-929157064360}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>JsonGeneratorTests</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)/../JsonGenerator;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)/../JsonGenerator;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_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="..\JsonGenerator\EscapedString.cpp" />
<ClCompile Include="..\JsonGenerator\JsonArrayBase.cpp" />
<ClCompile Include="..\JsonGenerator\JsonHashTableBase.cpp" />
<ClCompile Include="..\JsonGenerator\JsonValue.cpp" />
<ClCompile Include="..\JsonGenerator\StringBuilder.cpp" />
<ClCompile Include="EscapedStringTests.cpp" />
<ClCompile Include="JsonArrayTests.cpp" />
<ClCompile Include="JsonHashTableTests.cpp" />
<ClCompile Include="JsonValueTests.cpp" />
<ClCompile Include="Print.cpp" />
<ClCompile Include="StringBuilderTests.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\JsonGenerator\EscapedString.h" />
<ClInclude Include="..\JsonGenerator\JsonArray.h" />
<ClInclude Include="..\JsonGenerator\JsonArrayBase.h" />
<ClInclude Include="..\JsonGenerator\JsonHashTable.h" />
<ClInclude Include="..\JsonGenerator\JsonHashTableBase.h" />
<ClInclude Include="..\JsonGenerator\JsonObjectBase.h" />
<ClInclude Include="..\JsonGenerator\JsonValue.h" />
<ClInclude Include="..\JsonGenerator\Print.h" />
<ClInclude Include="..\JsonGenerator\Printable.h" />
<ClInclude Include="..\JsonGenerator\StringBuilder.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,84 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="JsonArrayTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonHashTableTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonValueTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonGenerator\JsonValue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonGenerator\StringBuilder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StringBuilderTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Print.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonGenerator\EscapedString.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonGenerator\JsonHashTableBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonGenerator\JsonArrayBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="EscapedStringTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\JsonGenerator\JsonArray.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\JsonHashTable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\JsonObjectBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\JsonValue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\Print.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\Printable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\StringBuilder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\EscapedString.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\JsonHashTableBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonGenerator\JsonArrayBase.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -1,124 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonArray.h"
#include "JsonHashTable.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Generator;
namespace JsonGeneratorTests
{
TEST_CLASS(JsonHashTableTests)
{
JsonHashTable<2> hash;
char buffer[256];
public:
TEST_METHOD(Empty)
{
outputMustBe("{}");
}
TEST_METHOD(OneString)
{
add("key", "value");
outputMustBe("{\"key\":\"value\"}");
}
TEST_METHOD(TwoStrings)
{
add("key1", "value1");
add("key2", "value2");
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
}
TEST_METHOD(OneStringOverCapacity)
{
add("key1", "value1");
add("key2", "value2");
add("key3", "value3");
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
}
TEST_METHOD(OneInteger)
{
add("key", 1);
outputMustBe("{\"key\":1}");
}
TEST_METHOD(OneDoubleFourDigits)
{
add<4>("key", 3.14159265358979323846);
outputMustBe("{\"key\":3.1416}");
}
TEST_METHOD(OneDoubleDefaultDigits)
{
add("key", 3.14159265358979323846);
outputMustBe("{\"key\":3.14}");
}
TEST_METHOD(OneNull)
{
add("key", (char*) 0);
outputMustBe("{\"key\":null}");
}
TEST_METHOD(OneTrue)
{
add("key", true);
outputMustBe("{\"key\":true}");
}
TEST_METHOD(OneFalse)
{
add("key", false);
outputMustBe("{\"key\":false}");
}
TEST_METHOD(OneEmptyNestedArray)
{
addNested("key", JsonArray<1>());
outputMustBe("{\"key\":[]}");
}
TEST_METHOD(OneEmptyNestedHash)
{
addNested("key", JsonHashTable<1>());
outputMustBe("{\"key\":{}}");
}
private:
void addNested(const char* key, JsonObjectBase& value)
{
hash.add<JsonObjectBase&>(key, value);
}
template<typename T>
void add(const char* key, T value)
{
hash.add(key, value);
}
template<int DIGITS>
void add(const char* key, double value)
{
hash.add<DIGITS>(key, value);
}
void outputMustBe(const char* expected)
{
size_t actual = hash.printTo(buffer, sizeof(buffer));
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), actual);
}
};
}

View File

@ -1,102 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "StringBuilder.h"
#include "JsonValue.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Internals;
namespace JsonGeneratorTests
{
TEST_CLASS(JsonValueTests)
{
char buffer[1024];
size_t returnValue;
public:
TEST_METHOD(String)
{
whenInputIs("hello");
outputMustBe("\"hello\"");
}
TEST_METHOD(Float)
{
whenInputIs(3.1415f);
outputMustBe("3.14");
}
TEST_METHOD(DoubleZeroDigits)
{
whenInputIs<0>(3.14159265358979323846);
outputMustBe("3");
}
TEST_METHOD(DoubleOneDigit)
{
whenInputIs<1>(3.14159265358979323846);
outputMustBe("3.1");
}
TEST_METHOD(DoubleTwoDigits)
{
whenInputIs<2>(3.14159265358979323846);
outputMustBe("3.14");
}
TEST_METHOD(Integer)
{
whenInputIs(314);
outputMustBe("314");
}
TEST_METHOD(Char)
{
whenInputIs('A');
outputMustBe("65");
}
TEST_METHOD(Short)
{
whenInputIs((short)314);
outputMustBe("314");
}
TEST_METHOD(Long)
{
whenInputIs(314159265L);
outputMustBe("314159265");
}
private:
template<int DIGITS>
void whenInputIs(double value)
{
StringBuilder sb(buffer, sizeof(buffer));
JsonValue jsonValue;
jsonValue.set<DIGITS>(value);
returnValue = jsonValue.printTo(sb);
}
template<typename T>
void whenInputIs(T value)
{
StringBuilder sb(buffer, sizeof(buffer));
JsonValue jsonValue;
jsonValue.set(value);
returnValue = jsonValue.printTo(sb);
}
void outputMustBe(const char* expected)
{
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), returnValue);
}
};
}

View File

@ -1,35 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#ifndef ARDUINO
#include "Print.h"
#include <cstdio>
size_t Print::print(const char s[])
{
size_t n = 0;
while (*s)
{
n += write(*s++);
}
return n;
}
size_t Print::print(double value, int digits)
{
char tmp[32];
sprintf(tmp, "%.*lg", digits+1, value);
return print(tmp);
}
size_t Print::print(long value)
{
char tmp[32];
sprintf(tmp, "%ld", value);
return print(tmp);
}
#endif

View File

@ -1,85 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "StringBuilder.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Internals;
namespace JsonGeneratorTests
{
TEST_CLASS(StringBuilderTests)
{
char buffer[20];
Print* sb;
size_t returnValue;
public:
TEST_METHOD_INITIALIZE(Initialize)
{
sb = new StringBuilder(buffer, sizeof(buffer));
}
TEST_METHOD(InitialState)
{
outputMustBe("");
}
TEST_METHOD(OverCapacity)
{
print("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
resultMustBe(19);
print("ABC");
resultMustBe(0);
outputMustBe("ABCDEFGHIJKLMNOPQRS");
}
TEST_METHOD(EmptyString)
{
print("");
resultMustBe(0);
outputMustBe("");
}
TEST_METHOD(OneString)
{
print("ABCD");
resultMustBe(4);
outputMustBe("ABCD");
}
TEST_METHOD(TwoStrings)
{
print("ABCD");
resultMustBe(4);
print("EFGH");
resultMustBe(4);
outputMustBe("ABCDEFGH");
}
private:
void print(const char* value)
{
returnValue = sb->print(value);
}
void outputMustBe(const char* expected)
{
Assert::AreEqual(expected, buffer);
}
void resultMustBe(size_t expected)
{
Assert::AreEqual(expected, returnValue);
}
};
}

View File

@ -1,12 +0,0 @@
/*
* malloc-free JSON parser for Arduino
* Benoit Blanchon 2014 - MIT License
*/
// This file is here to help the Arduino IDE find the .cpp files
#include "JsonParser/JsonArray.cpp"
#include "JsonParser/JsonHashTable.cpp"
#include "JsonParser/JsonObjectBase.cpp"
#include "JsonParser/JsonParserBase.cpp"
#include "JsonParser/jsmn.cpp"

View File

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

View File

@ -1,69 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonArray.h"
#include "JsonHashTable.h"
using namespace ArduinoJson::Parser;
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,43 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonObjectBase.h"
namespace ArduinoJson
{
namespace Parser
{
class JsonHashTable;
class JsonArray : public JsonObjectBase
{
friend class JsonParserBase;
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);
};
}
}

View File

@ -1,85 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include <string.h> // for strcmp()
#include "JsonArray.h"
#include "JsonHashTable.h"
using namespace ArduinoJson::Parser;
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,40 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonObjectBase.h"
namespace ArduinoJson
{
namespace Parser
{
class JsonArray;
class JsonHashTable : public JsonObjectBase
{
friend class JsonParserBase;
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);
};
}
}

View File

@ -1,67 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include <stdlib.h> // for strtol, strtod
#include "JsonObjectBase.h"
using namespace ArduinoJson::Parser;
int JsonObjectBase::getNestedTokenCount(jsmntok_t* token)
{
int tokensToVisit = token->size;
int count = 0;
while (tokensToVisit)
{
count++;
token++;
tokensToVisit--;
tokensToVisit += token->size;
}
return count;
}
bool JsonObjectBase::getBoolFromToken(jsmntok_t* token)
{
if (token == 0 || 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,53 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "jsmn.h"
namespace ArduinoJson
{
namespace Parser
{
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;
};
}
}

View File

@ -1,40 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonParserBase.h"
namespace ArduinoJson
{
namespace Parser
{
/*
* The JSON parser.
*
* You need to specifiy the number of token to be allocated for that parser.
* 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 JsonParserBase
{
public:
JsonParser()
: JsonParserBase(tokens, MAX_TOKENS)
{
}
private:
jsmntok_t tokens[MAX_TOKENS];
};
}
}

View File

@ -1,19 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonParserBase.h"
using namespace ArduinoJson::Parser;
jsmntok_t* JsonParserBase::parse(char* json)
{
jsmn_parser parser;
jsmn_init(&parser);
if (JSMN_SUCCESS != jsmn_parse(&parser, json, tokens, maxTokens))
return 0;
return tokens;
}

View File

@ -1,53 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "JsonHashTable.h"
#include "JsonArray.h"
namespace ArduinoJson
{
namespace Parser
{
class JsonParserBase
{
public:
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
*/
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* tokens;
int maxTokens;
jsmntok_t* parse(char* json);
};
}
}

View File

@ -1,404 +0,0 @@
Arduino JSON library - Parser
=============================
This library is an thin C++ wrapper around the *jsmn* tokenizer: http://zserge.com/jsmn.html
It's design to be very lightweight, works without any allocation on the heap (no malloc) and supports nested objects.
It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project.
Features
--------
* Based on the well-proven [jsmn](http://zserge.com/jsmn.html) tokenizer
* Supports nested objects
* Elegant API, very easy to use
* Fixed memory allocation (no malloc)
* Small footprint
* MIT License
Example
-------
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
JsonParser<32> parser;
JsonHashTable root = parser.parseHashTable(json);
char* sensor = root.getString("sensor");
long time = root.getLong("time");
JsonArray coords = root.getArray("data");
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;
### 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
------------
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.
<table>
<tr>
<th>Type</th>
<th>Size in bytes</th>
</tr>
<tr>
<td>Parser&lt;N&gt;</td>
<td>4 + 8 x N</td>
</tr>
<tr>
<td>JsonArray</td>
<td>4</td>
</tr>
<tr>
<td>JsonHashTable</td>
<td>4</td>
</tr>
</table>
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 is 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>

View File

@ -1,255 +0,0 @@
#include <stdlib.h>
#include "jsmn.h"
/**
* Allocates a fresh unused token from the token pull.
*/
static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *tok;
if (parser->toknext >= num_tokens) {
return NULL;
}
tok = &tokens[parser->toknext++];
tok->start = tok->end = -1;
tok->size = 0;
#ifdef JSMN_PARENT_LINKS
tok->parent = -1;
#endif
return tok;
}
/**
* Fills token type and boundaries.
*/
static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
int start, int end) {
token->type = type;
token->start = start;
token->end = end;
token->size = 0;
}
/**
* Fills next available token with JSON primitive.
*/
static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *token;
int start;
start = parser->pos;
for (; js[parser->pos] != '\0'; parser->pos++) {
switch (js[parser->pos]) {
#ifndef JSMN_STRICT
/* In strict mode primitive must be followed by "," or "}" or "]" */
case ':':
#endif
case '\t' : case '\r' : case '\n' : case ' ' :
case ',' : case ']' : case '}' :
goto found;
}
if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
parser->pos = start;
return JSMN_ERROR_INVAL;
}
}
#ifdef JSMN_STRICT
/* In strict mode primitive must be followed by a comma/object/array */
parser->pos = start;
return JSMN_ERROR_PART;
#endif
found:
token = jsmn_alloc_token(parser, tokens, num_tokens);
if (token == NULL) {
parser->pos = start;
return JSMN_ERROR_NOMEM;
}
jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
#ifdef JSMN_PARENT_LINKS
token->parent = parser->toksuper;
#endif
parser->pos--;
return JSMN_SUCCESS;
}
/**
* Filsl next token with JSON string.
*/
static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
jsmntok_t *tokens, size_t num_tokens) {
jsmntok_t *token;
int start = parser->pos;
parser->pos++;
/* Skip starting quote */
for (; js[parser->pos] != '\0'; parser->pos++) {
char c = js[parser->pos];
/* Quote: end of string */
if (c == '\"') {
token = jsmn_alloc_token(parser, tokens, num_tokens);
if (token == NULL) {
parser->pos = start;
return JSMN_ERROR_NOMEM;
}
jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
#ifdef JSMN_PARENT_LINKS
token->parent = parser->toksuper;
#endif
return JSMN_SUCCESS;
}
/* Backslash: Quoted symbol expected */
if (c == '\\') {
parser->pos++;
switch (js[parser->pos]) {
/* Allowed escaped symbols */
case '\"': case '/' : case '\\' : case 'b' :
case 'f' : case 'r' : case 'n' : case 't' :
break;
/* Allows escaped symbol \uXXXX */
case 'u':
/* TODO */
break;
/* Unexpected symbol */
default:
parser->pos = start;
return JSMN_ERROR_INVAL;
}
}
}
parser->pos = start;
return JSMN_ERROR_PART;
}
/**
* Parse JSON string and fill tokens.
*/
jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens,
unsigned int num_tokens) {
jsmnerr_t r;
int i;
jsmntok_t *token;
for (; js[parser->pos] != '\0'; parser->pos++) {
char c;
jsmntype_t type;
c = js[parser->pos];
switch (c) {
case '{': case '[':
token = jsmn_alloc_token(parser, tokens, num_tokens);
if (token == NULL)
return JSMN_ERROR_NOMEM;
if (parser->toksuper != -1) {
tokens[parser->toksuper].size++;
#ifdef JSMN_PARENT_LINKS
token->parent = parser->toksuper;
#endif
}
token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
token->start = parser->pos;
parser->toksuper = parser->toknext - 1;
break;
case '}': case ']':
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
#ifdef JSMN_PARENT_LINKS
if (parser->toknext < 1) {
return JSMN_ERROR_INVAL;
}
token = &tokens[parser->toknext - 1];
for (;;) {
if (token->start != -1 && token->end == -1) {
if (token->type != type) {
return JSMN_ERROR_INVAL;
}
token->end = parser->pos + 1;
parser->toksuper = token->parent;
break;
}
if (token->parent == -1) {
break;
}
token = &tokens[token->parent];
}
#else
for (i = parser->toknext - 1; i >= 0; i--) {
token = &tokens[i];
if (token->start != -1 && token->end == -1) {
if (token->type != type) {
return JSMN_ERROR_INVAL;
}
parser->toksuper = -1;
token->end = parser->pos + 1;
break;
}
}
/* Error if unmatched closing bracket */
if (i == -1) return JSMN_ERROR_INVAL;
for (; i >= 0; i--) {
token = &tokens[i];
if (token->start != -1 && token->end == -1) {
parser->toksuper = i;
break;
}
}
#endif
break;
case '\"':
r = jsmn_parse_string(parser, js, tokens, num_tokens);
if (r < 0) return r;
if (parser->toksuper != -1)
tokens[parser->toksuper].size++;
break;
case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
break;
#ifdef JSMN_STRICT
/* In strict mode primitives are: numbers and booleans */
case '-': case '0': case '1' : case '2': case '3' : case '4':
case '5': case '6': case '7' : case '8': case '9':
case 't': case 'f': case 'n' :
#else
/* In non-strict mode every unquoted value is a primitive */
default:
#endif
r = jsmn_parse_primitive(parser, js, tokens, num_tokens);
if (r < 0) return r;
if (parser->toksuper != -1)
tokens[parser->toksuper].size++;
break;
#ifdef JSMN_STRICT
/* Unexpected char in strict mode */
default:
return JSMN_ERROR_INVAL;
#endif
}
}
for (i = parser->toknext - 1; i >= 0; i--) {
/* Unmatched opened object or array */
if (tokens[i].start != -1 && tokens[i].end == -1) {
return JSMN_ERROR_PART;
}
}
return JSMN_SUCCESS;
}
/**
* Creates a new parser based over a given buffer with an array of tokens
* available.
*/
void jsmn_init(jsmn_parser *parser) {
parser->pos = 0;
parser->toknext = 0;
parser->toksuper = -1;
}

View File

@ -1,67 +0,0 @@
#ifndef __JSMN_H_
#define __JSMN_H_
/**
* JSON type identifier. Basic types are:
* o Object
* o Array
* o String
* o Other primitive: number, boolean (true/false) or null
*/
typedef enum {
JSMN_PRIMITIVE = 0,
JSMN_OBJECT = 1,
JSMN_ARRAY = 2,
JSMN_STRING = 3
} jsmntype_t;
typedef enum {
/* Not enough tokens were provided */
JSMN_ERROR_NOMEM = -1,
/* Invalid character inside JSON string */
JSMN_ERROR_INVAL = -2,
/* The string is not a full JSON packet, more bytes expected */
JSMN_ERROR_PART = -3,
/* Everything was fine */
JSMN_SUCCESS = 0
} jsmnerr_t;
/**
* JSON token description.
* @param type type (object, array, string etc.)
* @param start start position in JSON data string
* @param end end position in JSON data string
*/
typedef struct {
jsmntype_t type;
int start;
int end;
int size;
#ifdef JSMN_PARENT_LINKS
int parent;
#endif
} jsmntok_t;
/**
* JSON parser. Contains an array of token blocks available. Also stores
* the string being parsed now and current position in that string
*/
typedef struct {
unsigned int pos; /* offset in the JSON string */
int toknext; /* next token to allocate */
int toksuper; /* superior token node, e.g parent object or array */
} jsmn_parser;
/**
* Create JSON parser over an array of tokens
*/
void jsmn_init(jsmn_parser *parser);
/**
* Run JSON parser. It parses a JSON data string into and array of tokens, each describing
* a single JSON object.
*/
jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js,
jsmntok_t *tokens, unsigned int num_tokens);
#endif /* __JSMN_H_ */

View File

@ -1,244 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonParser.h"
#include <string>
using namespace std;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Parser;
namespace ArduinoJsonParserTests
{
TEST_CLASS(GbathreeBug)
{
char json[1024];
JsonParser<200> parser;
JsonHashTable root;
public:
TEST_METHOD_INITIALIZE(Initialize)
{
// BUG described here:
// http://forum.arduino.cc/index.php?topic=172578.msg1608219#msg1608219
strcpy(json, "{ \"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0,\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":10000,\"actintensity1\":50,\"actintensity2\":255,\"measintensity\":255,\"calintensity\":255,\"pulses\":[50,50,50],\"act\":[2,1,2,2],\"red\":[2,2,2,2],\"detectors\":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]],\"alta\":[2,2,2,2],\"altb\":[2,2,2,2],\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}");
root = parser.parseHashTable(json);
}
TEST_METHOD(Root)
{
Assert::IsTrue(root.success());
}
TEST_METHOD(ProtocolName)
{
string protocol_name = root.getString("protocol_name");
Assert::AreEqual(string("fluorescence"), protocol_name);
}
TEST_METHOD(Repeats)
{
Assert::AreEqual(1L, root.getLong("repeats"));
}
TEST_METHOD(Wait)
{
Assert::AreEqual(0L, root.getLong("wait"));
}
TEST_METHOD(Measurements)
{
Assert::AreEqual(3L, root.getLong("measurements"));
}
TEST_METHOD(Meas2_Light)
{
Assert::AreEqual(15L, root.getLong("meas2_light"));
}
TEST_METHOD(Meas1_Baseline)
{
Assert::AreEqual(0L, root.getLong("meas1_baseline"));
}
TEST_METHOD(Act_Light)
{
Assert::AreEqual(20L, root.getLong("act_light"));
}
TEST_METHOD(Pulsesize)
{
Assert::AreEqual(25L, root.getLong("pulsesize"));
}
TEST_METHOD(Pulsedistance)
{
Assert::AreEqual(10000L, root.getLong("pulsedistance"));
}
TEST_METHOD(Actintensity1)
{
Assert::AreEqual(50L, root.getLong("actintensity1"));
}
TEST_METHOD(Actintensity2)
{
Assert::AreEqual(255L, root.getLong("actintensity2"));
}
TEST_METHOD(Measintensity)
{
Assert::AreEqual(255L, root.getLong("measintensity"));
}
TEST_METHOD(Calintensity)
{
Assert::AreEqual(255L, root.getLong("calintensity"));
}
TEST_METHOD(Pulses)
{
// "pulses":[50,50,50]
JsonArray array = root.getArray("pulses");
Assert::IsTrue(array.success());
Assert::AreEqual(3, array.getLength());
for (int i = 0; i < 3; i++)
{
Assert::AreEqual(50L, array.getLong(i));
}
}
TEST_METHOD(Act)
{
// "act":[2,1,2,2]
JsonArray array = root.getArray("act");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
Assert::AreEqual(2L, array.getLong(0));
Assert::AreEqual(1L, array.getLong(1));
Assert::AreEqual(2L, array.getLong(2));
Assert::AreEqual(2L, array.getLong(3));
}
TEST_METHOD(Detectors)
{
// "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]]
JsonArray array = root.getArray("detectors");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
for (int i = 0; i < 4; i++)
{
Assert::AreEqual(4, array.getArray(i).getLength());
for (int j = 0; j < 4; j++)
Assert::AreEqual(34L, array.getArray(i).getLong(j));
}
}
TEST_METHOD(Alta)
{
// alta:[2,2,2,2]
JsonArray array = root.getArray("alta");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
for (int i = 0; i < 4; i++)
{
Assert::AreEqual(2L, array.getLong(i));
}
}
TEST_METHOD(Altb)
{
// altb:[2,2,2,2]
JsonArray array = root.getArray("altb");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
for (int i = 0; i < 4; i++)
{
Assert::AreEqual(2L, array.getLong(i));
}
}
TEST_METHOD(Measlights)
{
// "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
JsonArray array = root.getArray("measlights");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
for (int i = 0; i < 4; i++)
{
Assert::AreEqual(4, array.getArray(i).getLength());
for (int j = 0; j < 4; j++)
Assert::AreEqual(15L, array.getArray(i).getLong(j));
}
}
TEST_METHOD(Measlights2)
{
// "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
JsonArray array = root.getArray("measlights2");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
for (int i = 0; i < 4; i++)
{
Assert::AreEqual(4, array.getArray(i).getLength());
for (int j = 0; j < 4; j++)
Assert::AreEqual(15L, array.getArray(i).getLong(j));
}
}
TEST_METHOD(Altc)
{
// altc:[2,2,2,2]
JsonArray array = root.getArray("altc");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
for (int i = 0; i < 4; i++)
{
Assert::AreEqual(2L, array.getLong(i));
}
}
TEST_METHOD(Altd)
{
// altd:[2,2,2,2]
JsonArray array = root.getArray("altd");
Assert::IsTrue(array.success());
Assert::AreEqual(4, array.getLength());
for (int i = 0; i < 4; i++)
{
Assert::AreEqual(2L, array.getLong(i));
}
}
};
}

View File

@ -1,195 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonParser.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Parser;
namespace ArduinoJsonParserTests
{
TEST_CLASS(JsonArrayTests)
{
JsonArray array;
char json[256];
jsmntok_t tokens[32];
JsonParserBase parser = JsonParserBase(tokens, 32);
public:
TEST_METHOD(EmptyString)
{
whenInputIs("");
parseMustFail();
}
TEST_METHOD(TooFewClosingBrackets)
{
whenInputIs("[[]");
parseMustFail();
}
TEST_METHOD(TooManyClosingBrackets)
{
whenInputIs("[]]");
parseMustFail();
}
TEST_METHOD(EmptyArray)
{
whenInputIs("[]");
parseMustSucceed();
lengthMustBe(0);
}
TEST_METHOD(NotEnoughTokens)
{
setTokenCountTo(2);
whenInputIs("[1,2]");
parseMustFail();
itemMustNotExist(0);
}
TEST_METHOD(TwoIntegers)
{
setTokenCountTo(3);
whenInputIs("[1,2]");
parseMustSucceed();
lengthMustBe(2);
itemMustBe(0, 1L);
itemMustBe(1, 2L);
itemMustNotExist(2);
}
TEST_METHOD(TwoBooleans)
{
setTokenCountTo(3);
whenInputIs("[true,false]");
parseMustSucceed();
lengthMustBe(2);
itemMustBe(0, true);
itemMustBe(1, false);
itemMustNotExist(2);
}
TEST_METHOD(TwoStrings)
{
setTokenCountTo(3);
whenInputIs("[\"hello\",\"world\"]");
parseMustSucceed();
lengthMustBe(2);
itemMustBe(0, "hello");
itemMustBe(1, "world");
itemMustNotExist(2);
}
TEST_METHOD(TwoDimensionsArray)
{
setTokenCountTo(7);
whenInputIs("[[1,2],[3,4]]");
parseMustSucceed();
lengthMustBe(2);
itemMustBe(0, 0, 1L);
itemMustBe(0, 1, 2L);
itemMustBe(1, 0, 3L);
itemMustBe(1, 1, 4L);
itemMustNotExist(2);
}
TEST_METHOD(ThreeDimensionsArray)
{
setTokenCountTo(15);
whenInputIs("[[[1,2],[3,4]],[[5,6],[7,8]]]");
parseMustSucceed();
lengthMustBe(2);
itemMustBe(0, 0, 0, 1L);
itemMustBe(0, 0, 1, 2L);
itemMustBe(0, 1, 0, 3L);
itemMustBe(0, 1, 1, 4L);
itemMustBe(1, 0, 0, 5L);
itemMustBe(1, 0, 1, 6L);
itemMustBe(1, 1, 0, 7L);
itemMustBe(1, 1, 1, 8L);
itemMustNotExist(2);
}
private:
void setTokenCountTo(int n)
{
parser = JsonParserBase(tokens, n);
}
void whenInputIs(const char* input)
{
strcpy(json, input);
array = parser.parseArray(json);
}
void parseMustFail()
{
Assert::IsFalse(array.success());
lengthMustBe(0);
}
void parseMustSucceed()
{
Assert::IsTrue(array.success());
}
void lengthMustBe(int expected)
{
Assert::AreEqual(expected, array.getLength());
}
void itemMustBe(int index, long expected)
{
Assert::AreEqual(expected, array.getLong(index));
}
void itemMustBe(int index, bool expected)
{
Assert::AreEqual(expected, array.getBool(index));
}
void itemMustBe(int index, const char* expected)
{
Assert::AreEqual(expected, array.getString(index));
}
void itemMustBe(int index0, int index1, long expected)
{
Assert::AreEqual(expected, array.getArray(index0).getLong(index1));
}
void itemMustBe(int index0, int index1, int index2, long expected)
{
Assert::AreEqual(expected, array.getArray(index0).getArray(index1).getLong(index2));
}
void itemMustNotExist(int index)
{
Assert::IsFalse(array.getHashTable(index).success());
Assert::IsFalse(array.getArray(index).success());
Assert::IsFalse(array.getBool(index));
Assert::AreEqual(0.0, array.getDouble(index));
Assert::AreEqual(0L, array.getLong(index));
Assert::IsNull(array.getString(index));
}
};
}

View File

@ -1,171 +0,0 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonParser.h"
#include <string>
using namespace std;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Parser;
namespace ArduinoJsonParserTests
{
TEST_CLASS(JsonHashTableTests)
{
JsonHashTable hashTable;
JsonArray nestedArray;
char json[256];
jsmntok_t tokens[32];
JsonParserBase parser = JsonParserBase(tokens, 32);
public:
TEST_METHOD(EmptyString)
{
whenInputIs("");
parseMustFail();
}
TEST_METHOD(EmptyHashTable)
{
whenInputIs("{}");
parseMustSucceed();
}
TEST_METHOD(NotEnoughTokens)
{
setTokenCountTo(2);
whenInputIs("{\"key\":0}");
parseMustFail();
itemMustNotExist("key");
}
TEST_METHOD(TwoIntegers)
{
setTokenCountTo(5);
whenInputIs("{\"key1\":1,\"key2\":2}");
parseMustSucceed();
itemMustBe("key1", 1L);
itemMustBe("key2", 2L);
itemMustNotExist("key3");
}
TEST_METHOD(TwoBooleans)
{
setTokenCountTo(5);
whenInputIs("{\"key1\":true,\"key2\":false}");
parseMustSucceed();
itemMustBe("key1", true);
itemMustBe("key2", false);
itemMustNotExist("key3");
}
TEST_METHOD(TwoStrings)
{
setTokenCountTo(5);
whenInputIs("{\"key1\":\"hello\",\"key2\":\"world\"}");
parseMustSucceed();
itemMustBe("key1", "hello");
itemMustBe("key2", "world");
itemMustNotExist("key3");
}
TEST_METHOD(TwoNestedArrays)
{
setTokenCountTo(9);
whenInputIs("{\"key1\":[1,2],\"key2\":[3,4]}");
parseMustSucceed();
itemMustBeAnArray("key1");
arrayLengthMustBe(2);
arrayItemMustBe(0, 1L);
arrayItemMustBe(1, 2L);
arrayItemMustBe(2, 0L);
itemMustBeAnArray("key2");
arrayLengthMustBe(2);
arrayItemMustBe(0, 3L);
arrayItemMustBe(1, 4L);
arrayItemMustBe(2, 0L);
itemMustNotExist("key3");
}
private:
void setTokenCountTo(int n)
{
parser = JsonParserBase(tokens, n);
}
void whenInputIs(const char* input)
{
strcpy(json, input);
hashTable = parser.parseHashTable(json);
}
void parseMustFail()
{
Assert::IsFalse(hashTable.success());
}
void parseMustSucceed()
{
Assert::IsTrue(hashTable.success());
}
void itemMustBe(const char* key, long expected)
{
Assert::AreEqual(expected, hashTable.getLong(key));
}
void itemMustBe(const char* key, bool expected)
{
Assert::AreEqual(expected, hashTable.getBool(key));
}
void itemMustBe(const char* key, const char* expected)
{
Assert::AreEqual(expected, hashTable.getString(key));
}
void itemMustNotExist(const char* key)
{
Assert::IsFalse(hashTable.containsKey(key));
Assert::IsFalse(hashTable.getHashTable(key).success());
Assert::IsFalse(hashTable.getArray(key).success());
Assert::IsFalse(hashTable.getBool(key));
Assert::AreEqual(0.0, hashTable.getDouble(key));
Assert::AreEqual(0L, hashTable.getLong(key));
Assert::IsNull(hashTable.getString(key));
}
void itemMustBeAnArray(const char* key)
{
nestedArray = hashTable.getArray(key);
Assert::IsTrue(nestedArray.success());
}
void arrayLengthMustBe(int expected)
{
Assert::AreEqual(expected, nestedArray.getLength());
}
void arrayItemMustBe(int index, long expected)
{
Assert::AreEqual(expected, nestedArray.getLong(index));
}
};
}

View File

@ -1,108 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4DD596EF-0185-4AB4-A3C2-F20C496F7806}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ArduinoJsonParserTests</RootNamespace>
<ProjectName>JsonParserTests</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);..</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\JsonParser\jsmn.cpp" />
<ClCompile Include="..\JsonParser\JsonArray.cpp" />
<ClCompile Include="..\JsonParser\JsonHashTable.cpp" />
<ClCompile Include="..\JsonParser\JsonObjectBase.cpp" />
<ClCompile Include="..\JsonParser\JsonParserBase.cpp" />
<ClCompile Include="JsonArrayTests.cpp" />
<ClCompile Include="JsonHashTableTests.cpp" />
<ClCompile Include="GbathreeBug.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\JsonParser\jsmn.h" />
<ClInclude Include="..\JsonParser\JsonArray.h" />
<ClInclude Include="..\JsonParser\JsonHashTable.h" />
<ClInclude Include="..\JsonParser\JsonObjectBase.h" />
<ClInclude Include="..\JsonParser\JsonParser.h" />
<ClInclude Include="..\JsonParser\JsonParserBase.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,63 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\JsonParser\jsmn.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonParser\JsonArray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonParser\JsonHashTable.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonParser\JsonObjectBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonArrayTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GbathreeBug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonHashTableTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\JsonParser\JsonParserBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\JsonParser\jsmn.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonParser\JsonArray.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonParser\JsonHashTable.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonParser\JsonObjectBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonParser\JsonParser.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\JsonParser\JsonParserBase.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -1,25 +0,0 @@
#include "stdafx.h"
#include "CppUnitTest.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace ArduinoJsonParserTests
{
TEST_CLASS(TestHashGenerator)
{
public:
TEST_METHOD(TestMethod1)
{
JsonArray<5> arr;
arr.Add(1);
arr.Add("Hi!");
JsonHashTable<4> hash;
hash.Add("key1", 1);
hash.Add("key2", "Hello!");
hash.Add("key3", arr);
}
};
}

10
LICENSE.md Normal file
View File

@ -0,0 +1,10 @@
The MIT License (MIT)
---------------------
Copyright © 2014 Benoit BLANCHON
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,46 +1,65 @@
Arduino JSON library
====================
*A simple and efficient JSON library for embedded systems.*
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson)
It's design to be very lightweight, works without any allocation on the heap (no malloc).
*An elegant and efficient JSON library for embedded systems.*
It's design to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc).
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
--------
* JSON decoding: [more details here](/JsonParser/)
* JSON encoding: [more details here](/JsonGenerator/)
* JSON decoding
* JSON encoding (with optional indentation)
* Elegant API, very easy to use
* Fixed memory allocation (no malloc)
* Small footprint
* MIT License
Feature comparison
------------------
Quick start
-----------
| Library | Memory allocation | Nested objects | Parser size | Encoder size |
| ------------ | ----------------- | -------------- | ----------- | ------------- |
| Arduino JSON | static | yes | 2616 Bytes | 628 bytes |
| json-arduino | dynamic | no | 3348 (+28%) | not supported |
| aJson | dynamic | yes | 5088 (+94%) | 4678 (+640%) |
#### Decoding / Parsing
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
"Parser size" was measured with a program parsing `{"sensor":"outdoor","value":25.6}`.
For each library, I wrote a program that extracts a string and a float. I subtracted the size of a program doing the same without any JSON parsing involved. [Source files are here](https://gist.github.com/bblanchon/e8ba914a7109f3642c0f).
StaticJsonBuffer<200> jsonBuffer;
"Encoder size" was measured with a program generating `{"sensor":"outdoor","value":25.6}`.
[Source files are here](https://gist.github.com/bblanchon/60224e9dcfeab4ddc7e9).
JsonObject& root = jsonBuffer.parseObject(json);
In each case the target platform was an Arduino Duemilanove and Arduino IDE 1.0.5 was used.
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
Links: [json-arduino](https://github.com/not404/json-arduino), [aJson](https://github.com/interactive-matter/aJson)
[See complete guide](/doc/Decoding JSON.md)
#### Encoding / Generating
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["sensor"] = "gps";
root["time"] = 1351824120;
JsonArray& data = root.createNestedArray("data");
data.add(48.756080, 6); // 6 is the number of decimals to print
data.add(2.302038, 6); // if not specified, 2 digits are printed
root.printTo(Serial);
// This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
[See complete guide](/doc/Encoding JSON.md)
Testimonials
------------
From Arduino's Forum user `jflaplante`:
> I tried the [aJson and json-arduino] before trying your library. I always ran into memory problem after a while.
> I tried aJson json-arduino before trying your library. I always ran into memory problem after a while.
> I have no such problem so far with your library. It is working perfectly with my web services.
From Arduino's Forum user `gbathree`:
@ -49,8 +68,12 @@ From Arduino's Forum user `gbathree`:
From StackOverflow user `thegreendroid`:
> It has a really elegant, simple API and it works like a charm on embedded and Windows/Linux platforms. We recently started using this on an embedded project and I can vouch for its quality.
Links
-----
From GitHub user `zacsketches`:
* [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/)
> Thanks for a great library!!!
> I've been watching you consistently develop this library over the past six months, and I used it today for a publish and subscribe architecture designed to help hobbyists move into more advanced robotics. Your library allowed me to implement remote subscription in order to facilitate multi-processor robots.
> ArduinoJson saved me a week's worth of time!!
---
Found this library useful? [Help me back with a donation!](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=donate%40benoitblanchon%2efr&lc=GB&item_name=Benoit%20Blanchon&item_number=Arduino%20JSON&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted) :smile:

102
doc/Avoiding pitfalls.md Normal file
View File

@ -0,0 +1,102 @@
Avoiding common pitfalls in Arduino JSON
========================================
As `StaticJsonBuffer` is the corner stone of this library, you'll see that every pitfall listed here are related to a wrong understanding of the memory model.
Make sure you read [Arduino JSON memory model](Memory model.md) before going further.
## 1. Make `StaticJsonBuffer` big enough
By design, the library has no way to tell you why `parseArray()` or `parseObject()` failed.
There are basically two reasons why they may fail:
1. the JSON string is invalid,
2. the JSON string contains more values that the buffer can store.
So, if you are sure the JSON string is correct and you still can't parse it, you should try to increase the size of the `StaticJsonBuffer`.
## 2. Make sure everything fits in memory
You may go into unpredictable trouble if you allocate more memory than your processor really has.
It's a very common issue in embedded development.
To diagnose this, look at every big objects in you code and sum their size to check that they fit in RAM.
For example, don't do this:
char json[1024]; // 1 KB
StaticJsonBuffer<512> buffer; // 514 B
because it may be too big for a processor with only 2 KB: you need free memory to store other variables and the call stack.
That is why an 8-bit processor is not able to parse long and complex JSON strings.
## 3. Keep the `StaticJsonBuffer` in memory long enough
Remember that `StaticJsonBuffer`'s function return references.
References don't contain data, they are just pointer to the actual.
So they can only work if the actual data is in memory.
For example, don't do this:
JsonArray& getArray(char* json)
{
StaticJsonBuffer<200> buffer;
return buffer.parseArray(json);
}
because the local variable `buffer` will be *removed* from memory when the function `parseArray()` returns, and the `JsonArray&` will point to an invalid location.
## 4. Don't reuse the same `StaticJsonBuffer`
During is lifetime a `StaticJsonBuffer` growth until it's discarded. If you try to reuse the same instance several time, it will rapidly get full.
For this reason, you should not use a global variable for your `StaticJsonBuffer`. I don't think there is any scenario in which a global `StaticJsonBuffer` would be a valid option.
The best practice is to declare it in a local scope, so that it's discarded as soon as possible. My advice it to declare it in a function which unique role is to handle the JSON serialization.
## 5. Keep the JSON string in memory long enough
The library never make memory duplication.
This has an important implication on string values, it means that the library will return pointer to chunks of the string.
For instance, let's imagine that you parse `["hello","world"]`, like this:
char[] json = "[\"hello\",\"world\"]";
StaticJsonBuffer<32> buffer;
JsonArray& array = buffer.parseArray(json);
const char* first = array[0];
const char* second = array[1];
In that case, both `first` and `second` are pointers to the content of the original string `json`.
So this will only work if `json` is still in memory.
## 6. JSON string is altered
If you read carefully the previous section, you may have come to the conclusion that the JSON parser modifies the JSON string.
Indeed, the parser modifies the string for two reasons:
1. it inserts `\0` to terminate substrings,
2. it translate escaped characters like `\n` or `\t`.
Most of the time this wont be an issue, but there are some corner cases that can be problematic.
Let take the example bellow:
char[] json = "[\"hello\",\"world\"]";
StaticJsonBuffer<32> buffer;
JsonArray& array = buffer.parseArray(json);
If you replace it by:
char* json = "[\"hello\",\"world\"]";
StaticJsonBuffer<32> buffer;
JsonArray& array = buffer.parseArray(json);
Depending on your platform, you may have an exception because the parser tries to write at a location that is read-only.
In the first case `char json[]` declares an array of `char` initialized to the specified string.
In the second case `char* json` declares a pointer to a read-only string, in fact it should be a `const char*` instead of a `char*`.

15
doc/Contributing.md Normal file
View File

@ -0,0 +1,15 @@
Contributing to Arduino JSON
============================
If you want to contribute to the project, please:
1. Use GitHub pull request feature
2. Follow the coding conventions
3. Write tests
About the coding conventions: I try to follow the [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html) with few variations to match the Arduino conventions.
I use [ClangFormat](http://clang.llvm.org/docs/ClangFormat.html) to format the code for me.
I use [CppLint](http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py) to detect non-compliant stuff.
You should have a look at the `scripts/` folder as it contains a few helpers scripts.

148
doc/Decoding JSON.md Normal file
View File

@ -0,0 +1,148 @@
Decoding JSON with Arduino JSON
===============================
Before writing any code, don't forget to include the header:
#include <ArduinoJson.h>
For instructions on how to install the library, please read [Using the library with Arduino](Using the library with Arduino.md) or [Using the library without Arduino](Using the library without Arduino.md).
## Example
Here an example that parse the string `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`:
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
//
// Step 1: Reserve memory space
//
StaticJsonBuffer<200> jsonBuffer;
//
// Step 2: Deserialize the JSON string
//
JsonObject& root = jsonBuffer.parseObject(json);
if (!root.success())
{
Serial.println("parseObject() failed");
return;
}
//
// Step 3: Retrieve the values
//
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
## Step 1: Reserve memory space
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer`.
Before continuing please read the page [Arduino JSON memory model](Memory model.md) that explains everything you need to know about `StaticJsonBuffer`.
## Step 2: Parse the JSON string
You invoke the JSON parser through the instance of `StaticJsonBuffer`.
It exposes two functions for parsing JSON:
1. `parseArray()` that returns a reference to a `JsonArray`
2. `parseObject()` that returns a reference to a `JsonObject`
Let's see an example.
Say we want to parse `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`, it's an object so we call `parseObject()` as follows:
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
JsonObject& root = jsonBuffer.parseObject(json);
As you can see `parseObject()` takes a `char*` as a parameter.
Be careful, it's not a `const char*`, the memory must be writable.
Indeed, the parser will modify the string in two cases:
1. to insert string endings (character `\0`),
2. to translate escaped characters (like `\n` or `\t`).
Another thing that you must keep in mind is that the string (`char json[]` in the example above) must stay in memory during the whole parsing process.
That is because the in memory object tree will store pointer to chunks of the string, so as to avoid any memory duplication.
Now, to check if the parsing was successful, you can call `JsonObject::success()`:
if (!root.success())
{
// Parsing fail
}
The result can be `false` for tree reasons:
1. the JSON string is invalid,
2. the JSON string doesn't represent an object,
3. the `StaticJsonBuffer` is too small.
We just saw how to parse an object, there is nothing more to say for arrays, the procedure is exactly the same.
## Step 3: Retrieve the values
Now that the object or array is in memory, you can extract the data very easily.
In this section, we'll see how to do it with a `JsonObject`.
Once again, there is nothing more to say about arrays, `JsonArray` works exactly the same as `JsonObject`.
#### Subscript operator
The simplest way is to use the subscript operator of `JsonObject`:
const char* sensor = root["sensor"];
long time = root["time"];
You can chain the subscript operator if you have nested arrays or objects:
double latitude = root["data"][0];
double longitude = root["data"][1];
But alternatively, you can get a reference to the nested array:
JsonArray& nestedArray = root["data"];
#### Casting values
In the previous examples, the values were implicitly casted to the target type.
You can also do this explicitly
const char* sensor = root["sensor"].asString();
long time = root["time"].as<long>();
JsonArray& nestedArray = root["data"].asArray();
If the actual value doesn't match the target type, a default value will be return:
1. `false` for boolean values
2. `0` for integer values
3. `NULL` for string values
4. `JsonArray::invalid()` for nested arrays
5. `JsonObject::invalid()` for nested object
#### Check values
If you want to know if some value is present, call `containsKey()`:
if (root.contains("extra"))
{
// root["extra"] is valid
}
If you want to check the type value has a certain type, call `is<T>()`:
if (root["extra"].is<JsonArray&>())
{
// root["extra"] is an array
}
You can also iterate through the key-value pairs of the object:
for (JsonObject::itertor it=root.begin(); it!=root.end(); ++it)
{
Serial.println(it->key);
Serial.println(i->value.asString());
}

140
doc/Encoding JSON.md Normal file
View File

@ -0,0 +1,140 @@
Encoding JSON with Arduino JSON
===============================
Before writing any code, don't forget to include the header:
#include <ArduinoJson.h>
For instructions on how to install the library, please read [Using the library with Arduino](Using the library with Arduino.md) or [Using the library without Arduino](Using the library without Arduino.md).
## Example
Here is an example to generate `{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}`
//
// Step 1: Reserve memory space
//
StaticJsonBuffer<200> jsonBuffer;
//
// Step 2: Build object tree in memory
//
JsonObject& root = jsonBuffer.createObject();
root["sensor"] = "gps";
root["time"] = 1351824120;
JsonArray& data = root.createNestedArray("data");
data.add(48.756080, 6); // 6 is the number of decimals to print
data.add(2.302038, 6); // if not specified, 2 digits are printed
//
// Step 3: Generate the JSON string
//
root.printTo(Serial);
## Step 1: Reserve memory space
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer`.
Before continuing please read the page [Arduino JSON memory model](Memory model.md) that explains everything you need to know about `StaticJsonBuffer`.
## Step 2: Build object tree in memory
Now that you have enough memory hold by the `StaticJsonBuffer`, you can use it to build your in-memory representation of the JSON string.
#### Arrays
You create an array like this:
JsonArray& array = jsonBuffer.createArray();
Don't forget the `&` after `JsonArray`, it needs to be a reference to the array.
Then you can add strings, integer, booleans, etc:
array.add("bazinga!");
array.add(42);
array.add(true);
There are two syntaxes for floating point values:
array.add(3.1415, 4); // 4 digits: "3.1415"
array.add(3.1415); // 2 digits: "3.14"
> ##### About floating point precision
> The overload of `add()` with 2 parameters allows you to specify the number of decimals to save in the JSON string.
> When you use the overload with one parameter, you use the default number of decimals which is 2.
> Note that this behavior is the exact same as Arduino's `Print::print(double,int);` which is implemented by `Serial`, so you may already be familiar with this behavior.
You can add a nested array or object if you have a reference to it.
Or simpler, you can create nested array or nested objects from the array:
JsonArray& nestedArray = array.createNestedArray();
JsonObject& nestedObject = array.createNestedObject();
#### Objects
You create an object like this:
JsonObject& object = jsonBuffer.createObject();
Again, don't forget the `&` after `JsonObject`, it needs to be a reference to the object.
Then you can add strings, integer, booleans, etc:
object["key1"] = "bazinga!";
object["key2"] = 42;
object["key3"] = true;
As for the arrays, there are two syntaxes for the floating point values:
object["key4"].set(3.1415, 4); // 4 digits "3.1415"
object["key5"] = 3.1415; // default: 2 digits "3.14"
You can add a nested array or object if you have a reference to it.
Or simpler, you can create nested array or nested objects from the object:
JsonArray& nestedArray = object.createNestedArray("key6");
JsonObject& nestedObject = object.createNestedObject("key7");
> ##### Other JsonObject functions
> * `object.add(key, value)` is a synonym for `object[key] = value`
> * `object.containsKey(key)` returns `true` is the `key` is present in `object`
> * `object.remove(key)` removes the `value` associated with `key`
## Step 3: Generate the JSON string
There are two ways tho get the resulting JSON string.
Depending on your project, you may need to dump the string in a classic `char[]` or send it to a `Print` implementation like `Serial` or `EthernetClient `.
Both ways are the easy way :-)
#### Use a classic `char[]`
Whether you have a `JsonArray&` or a `JsonObject&`, simply call `printTo()` with the destination buffer, like so:
char buffer[256];
array.printTo(buffer, sizeof(buffer));
> ##### Want an indented output?
> By default the generated JSON is as small as possible. It contains no extra space, nor line break.
> But if you want an indented, more readable output, you can.
> Simply call `prettyPrintTo` instead of `printTo()`:
>
> array.prettyPrintTo(buffer, sizeof(buffer));
#### Send to a `Print` implementation
It's very likely that the generated JSON will end up in a stream like `Serial` or `EthernetClient `, so you can save some time and memory by doing this:
array.printTo(Serial);
And, of course if you need an indented JSON string:
array.prettyPrintTo(Serial);
> ##### About the Print interface
> The library is designed to send the JSON string to an implementation of the `Print` interface that is part of Arduino.
> In the example above we used `Serial`, but they are many other implementations that would work as well, including: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`, `Wire`...
> When you use this library out of the Arduino environment, it will use it's own implementation of `Print` and everything will be the same.

58
doc/Memory model.md Normal file
View File

@ -0,0 +1,58 @@
Arduino JSON memory model
=========================
## Fixed memory allocation
### Introducing `StaticJsonBuffer`
Arduino JSON uses a preallocated memory pool to store the object tree, this is done by the `StaticJsonBuffer` class.
Before using any function of the library you need to create a `StaticJsonBuffer`. Then you can use this instance to create arrays and objects, or parse a JSON string.
`StaticJsonBuffer` has a template parameter that determines its capacity. For example, the following line create a `StaticJsonBuffer` with a capacity of 200 bytes:
StaticJsonBuffer<200> jsonBuffer;
The bigger the buffer is, the more complex the object tree can be, but also the more memory you need.
### How to determine the buffer size?
So the big question you should have in mind right now is *How can I determine the size?*.
There are basically two approaches here:
1. either you can predict the content of the object tree,
2. or, you know how much memory is available.
In the first case, you know some constraints on the object tree. For instance, let's say that your know in advance (and by that I mean "at compilation time") that you want to generate an object with 3 values, one of them being an array with 2 values, like the following:
{"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
To determine the memory usage of this object tree, you use the two macros `JSON_ARRAY_SIZE(n)` and `JSON_OBJECT_SIZE(n)`, both take the number of elements as an argument.
For the example above, it would be:
const int BUFFER_SIZE = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2);
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
In the second case, let's say you dynamically generate a JSON object tree of a random complexity so you can't put a limit based on that. But on the other hand, you don't want your program to crash because the object tree doesn't fit in memory.
The solution here is to determine how much memory is available, or in other words how much memory you can afford for the JSON object tree.
### Why choosing fixed allocation?
This fixed allocation approach may seem a bit strange, especially if your a desktop application developer used to dynamic allocation, but it make a lot of sense in an embedded context:
1. the code is smaller
2. it uses less memory
3. it doesn't create memory fragmentation
4. it predictable
Don't forget that the memory is "freed" as soon as the `StaticJsonBuffer` is out of scope, like any other variable. It only hold the memory for a short amount of time.
## Memory usage
#### Object size for 8-bit AVR
| Type | Size |
|-------------------------|------------|
| JsonArray of N element | 4 + 8 * N |
| JsonObject of N element | 4 + 10 * N |

View File

@ -0,0 +1,80 @@
Migrating code written for Arduino JSON v3 to v4
================================================
Arduino JSON v4 was a major rewrite of the library, and the API changed significantly.
## Includes
Arduino JSON v3 had two include files:
#include <JsonParser.h>
#include <JsonGenerator.h>
Arduino JSON v4 only has one:
#include <ArduinoJson.h>
## Namespaces
Arduino JSON v3 had two namespaces:
using namespace ArduinoJson::Parser;
using namespace ArduinoJson::Generator;
Arduino JSON v4 doesn't require the `using namespace` statement.
It has a namespace but the `using namespace` is done in the header file.
## StaticJsonBuffer
Arduino JSON v3 had different memory allocation models for the parser:
JsonParser<16> parser; // 16 being the capacity in "tokens"
and for the generator:
JsonArray<4> array; // 4 being the number of element
JsonObject<4> object;
Arduino JSON v4 only has one memory allocation model:
StaticJsonBuffer<128> buffer; // 128 being the capacity in bytes
## Return values for the parser
Arduino JSON v3 returned value types:
JsonArray array = parser.parseArray(json);
JsonObject object = parser.parseObject(json);
Arduino JSON v4 returns references types:
JsonArray& array = buffer.parseArray(json);
JsonObject& object = buffer.parseObject(json);
Everything else is compatible
## Creating arrays and objects
Arduino JSON v3 allowed to create `JsonArray` and `JsonObject` directly:
JsonArray<4> array;
JsonObject<4> object;
Arduino JSON v4 requires that you use a `StaticJsonBuffer` for that:
JsonArray& array = buffer.createArray();
JsonObject& object = buffer.createObject();
Note: you don't have to specify the capacity anymore.
## Printable interface
Arduino JSON v3 used to implement the Printable interface, which allowed statements like:
Serial.print(array);
But Arduino JSON v4 doesn't, instead you need to write this:
array.printTo(Serial);
Note: there was a good reason for removing that feature, and it's reducing the size of `JsonArray` and `JsonObject`.

View File

@ -0,0 +1,30 @@
Using the library with Arduino
==============================
This library is primarily design to be used with the Arduino IDE and therefore has a simplified setup procedure for that environment.
If you don't use the Arduino IDE, please read [Using the library without Arduino](Using the library without Arduino.md).
## Install the library
[Download the zip package](https://github.com/bblanchon/ArduinoJson/releases) and extract it to:
<your Arduino Sketch folder>/libraries/ArduinoJson
Then restart the Arduino IDE.
## Run the examples sketches
Click `File` / `Example` / `ArduinoJson`.
![Screen capture of Arduino IDE](http://i.imgur.com/g5UwkVh.png)
## Use the library in your sketches
Just add the following line at the top of your program:
#include <ArduinoJson.h>
Then follow the instructions:
1. [Parsing JSON](Parsin JSON.md)
2. [Generating JSON](Generating JSON.md)

View File

@ -0,0 +1,37 @@
Using the library without Arduino
=================================
This library is primarily design to be used with the Arduino IDE and therefore has a simplified setup procedure for that environment.
If you use the Arduino IDE, please read [Using the library with Arduino](Using the library with Arduino.md).
However, it can be used without Arduino IDE with very little effort.
## Compiling the library
Step 1: Download source code:
git clone https://github.com/bblanchon/ArduinoJson.git
Step 2: Generate the `Makefile` for your environment
cd ArduinoJson
cmake .
Step 3: Build
make
## File paths
Assuming you installed the library into `<arduino-json>`, you need to add:
1. `<arduino-json>/include` to your include path
2. `<arduino-json>/lib` to your library path
----------
You are now ready to follow the instructions:
1. [Parsing JSON](Parsin JSON.md)
2. [Generating JSON](Generating JSON.md)

View File

@ -0,0 +1,30 @@
/*
* Arduino JSON library - IndentedPrint example
* Benoit Blanchon 2014 - MIT License
*/
#include <ArduinoJson.h>
using namespace ArduinoJson::Internals;
void setup() {
Serial.begin(9600);
IndentedPrint serial(Serial);
serial.setTabSize(4);
serial.println("This is at indentation 0");
serial.indent();
serial.println("This is at indentation 1");
serial.println("This is also at indentation 1");
serial.indent();
serial.println("This is at indentation 2");
serial.unindent();
serial.unindent();
serial.println("This is back at indentation 0");
}
void loop() {
// not used in this example
}

View File

@ -1,29 +1,42 @@
/*
* Arduino JSON library - Generator example
* Benoit Blanchon 2014 - MIT License
*/
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <JsonGenerator.h>
#include <ArduinoJson.h>
using namespace ArduinoJson::Generator;
void setup() {
Serial.begin(9600);
void setup()
{
Serial.begin(9600);
StaticJsonBuffer<200> jsonBuffer;
JsonArray<2> array;
array.add<6>(48.756080); // 6 is the number of decimals to print
array.add<6>(2.302038); // if not specified, 2 digits are printed
JsonObject& root = jsonBuffer.createObject();
root["sensor"] = "gps";
root["time"] = 1351824120;
JsonHashTable<3> root;
root.add("sensor", "gps");
root.add("time", 1351824120);
root.add("data", array);
JsonArray& data = root.createNestedArray("data");
data.add(48.756080, 6); // 6 is the number of decimals to print
data.add(2.302038, 6); // if not specified, 2 digits are printed
Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
root.printTo(Serial);
// This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
Serial.println();
root.prettyPrintTo(Serial);
// This prints:
// {
// "sensor": "gps",
// "time": 1351824120,
// "data": [
// 48.756080,
// 2.302038
// ]
// }
}
void loop()
{
void loop() {
// not used in this example
}

View File

@ -1,44 +1,37 @@
/*
* Arduino JSON library - Parser Example
* Benoit Blanchon 2014 - MIT License
*/
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include <JsonParser.h>
#include <ArduinoJson.h>
using namespace ArduinoJson::Parser;
void setup() {
Serial.begin(9600);
void setup()
{
Serial.begin(9600);
StaticJsonBuffer<200> jsonBuffer;
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
JsonParser<16> parser;
JsonObject& root = jsonBuffer.parseObject(json);
JsonHashTable root = parser.parseHashTable(json);
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
if (!root.success())
{
Serial.println("JsonParser.parseHashTable() failed");
return;
}
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
char* sensor = root.getString("sensor");
Serial.println(sensor);
long time = root.getLong("time");
Serial.println(time);
JsonArray coords = root.getArray("data");
for (int i = 0; i < coords.getLength(); i++)
{
double value = coords.getDouble(i);
Serial.println(value, 6);
}
Serial.println(sensor);
Serial.println(time);
Serial.println(latitude, 6);
Serial.println(longitude, 6);
}
void loop()
{
void loop() {
// not used in this example
}

11
include/ArduinoJson.h Normal file
View File

@ -0,0 +1,11 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include "../include/ArduinoJson/JsonArray.hpp"
#include "../include/ArduinoJson/JsonObject.hpp"
#include "../include/ArduinoJson/StaticJsonBuffer.hpp"
using namespace ArduinoJson;

View File

@ -0,0 +1,31 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#ifndef ARDUINO
#include <stddef.h>
#include <stdint.h>
// This class reproduces Arduino's Print
class Print {
public:
virtual ~Print() {}
virtual size_t write(uint8_t) = 0;
size_t print(const char[]);
size_t print(double, int = 2);
size_t print(long);
size_t println();
};
#else
#include <Print.h>
#endif

View File

@ -0,0 +1,54 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
// Decorator on top of Print to allow indented output.
// This class is used by JsonPrintable::prettyPrintTo() but can also be used
// for your own purpose, like logging.
class IndentedPrint : public Print {
public:
explicit IndentedPrint(Print &p) : sink(&p) {
level = 0;
tabSize = 2;
isNewLine = true;
}
virtual size_t write(uint8_t);
// Adds one level of indentation
void indent() {
if (level < MAX_LEVEL) level++;
}
// Removes one level of indentation
void unindent() {
if (level > 0) level--;
}
// Set the number of space printed for each level of indentation
void setTabSize(uint8_t n) {
if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE;
}
private:
Print *sink;
uint8_t level : 4;
uint8_t tabSize : 3;
bool isNewLine : 1;
size_t writeTabs();
static const int MAX_LEVEL = 15; // because it's only 4 bits
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
};
}
}

View File

@ -0,0 +1,42 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonBuffer.hpp"
#include "../JsonVariant.hpp"
namespace ArduinoJson {
namespace Internals {
// Parse JSON string to create JsonArrays and JsonObjects
// This internal class is not indended to be used directly.
// Instead, use JsonBuffer.parseArray() or .parseObject()
class JsonParser {
public:
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
: _buffer(buffer), _ptr(json), _nestingLimit(nestingLimit) {}
JsonArray &parseArray();
JsonObject &parseObject();
private:
bool skip(char charToSkip);
bool skip(const char *wordToSkip);
void skipSpaces();
void parseAnythingTo(JsonVariant &destination);
inline void parseBooleanTo(JsonVariant &destination);
inline void parseNullTo(JsonVariant &destination);
inline void parseNumberTo(JsonVariant &destination);
inline const char *parseString();
JsonBuffer *_buffer;
char *_ptr;
uint8_t _nestingLimit;
};
}
}

View File

@ -0,0 +1,54 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "IndentedPrint.hpp"
#include "JsonWriter.hpp"
#include "Prettyfier.hpp"
#include "StringBuilder.hpp"
namespace ArduinoJson {
namespace Internals {
// Implements all the overloads of printTo() and prettyPrintTo()
// Caution: this class use a template parameter to avoid virtual methods.
// This is a bit curious but allows to reduce the size of JsonVariant, JsonArray
// and JsonObject.
template <typename T>
class JsonPrintable {
public:
size_t printTo(Print &print) const {
JsonWriter writer(print);
downcast().writeTo(writer);
return writer.bytesWritten();
}
size_t printTo(char *buffer, size_t bufferSize) const {
StringBuilder sb(buffer, bufferSize);
return printTo(sb);
}
size_t prettyPrintTo(IndentedPrint &print) const {
Prettyfier p(print);
return printTo(p);
}
size_t prettyPrintTo(char *buffer, size_t bufferSize) const {
StringBuilder sb(buffer, bufferSize);
return prettyPrintTo(sb);
}
size_t prettyPrintTo(Print &print) const {
IndentedPrint indentedPrint = IndentedPrint(print);
return prettyPrintTo(indentedPrint);
}
private:
const T &downcast() const { return *static_cast<const T *>(this); }
};
}
}

View File

@ -0,0 +1,28 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
namespace ArduinoJson {
// Forward declarations
class JsonArray;
class JsonObject;
namespace Internals {
// A union that defines the actual content of a JsonVariant.
// The enum JsonVariantType determines which member is in use.
union JsonVariantContent {
bool asBoolean;
double asDouble; // asDouble is also used for float
long asLong; // asLong is also used for char, short and int
const char* asString; // asString can be null
JsonArray* asArray; // asArray cannot be null
JsonObject* asObject; // asObject cannot be null
};
}
}

View File

@ -0,0 +1,33 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
namespace ArduinoJson {
namespace Internals {
// Enumerated type to know the current type of a JsonVariant.
// The value determines which member of JsonVariantContent is used.
enum JsonVariantType {
JSON_INVALID, // a special state for JsonVariant::invalid()
JSON_UNDEFINED, // the JsonVariant has not been initialized
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
JSON_BOOLEAN, // the JsonVariant stores a bool
JSON_STRING, // the JsonVariant stores a const char*
JSON_LONG, // the JsonVariant stores a long
// The following values are reserved for double values
// Multiple values are used for double, depending on the number of decimal
// digits that must be printed in the JSON output.
// This little trick allow to save one extra member in JsonVariant
JSON_DOUBLE_0_DECIMALS
// JSON_DOUBLE_1_DECIMAL
// JSON_DOUBLE_2_DECIMALS
// ...
};
}
}

View File

@ -0,0 +1,64 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../Arduino/Print.hpp"
#include "QuotedString.hpp"
namespace ArduinoJson {
namespace Internals {
// Writes the JSON tokens to a Print implementation
// This class is used by:
// - JsonArray::writeTo()
// - JsonObject::writeTo()
// - JsonVariant::writeTo()
// Its derived by PrettyJsonWriter that overrides some members to add
// indentation.
class JsonWriter {
public:
explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {}
// Returns the number of bytes sent to the Print implementation.
// This is very handy for implementations of printTo() that must return the
// number of bytes written.
size_t bytesWritten() { return _length; }
void beginArray() { write('['); }
void endArray() { write(']'); }
void beginObject() { write('{'); }
void endObject() { write('}'); }
void writeColon() { write(':'); }
void writeComma() { write(','); }
void writeString(const char *value) {
_length += QuotedString::printTo(value, _sink);
}
void writeLong(long value) { _length += _sink.print(value); }
void writeBoolean(bool value) {
_length += _sink.print(value ? "true" : "false");
}
void writeDouble(double value, uint8_t decimals) {
_length += _sink.print(value, decimals);
}
protected:
void write(char c) { _length += _sink.write(c); }
void write(const char *s) { _length += _sink.print(s); }
Print &_sink;
size_t _length;
private:
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
};
}
}

View File

@ -0,0 +1,74 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../JsonBuffer.hpp"
#include "ListConstIterator.hpp"
#include "ListIterator.hpp"
#include "PlacementNew.hpp"
namespace ArduinoJson {
namespace Internals {
// A singly linked list of T.
// The linked list is composed of ListNode<T>.
// It is derived by JsonArray and JsonObject
template <typename T>
class List {
public:
typedef T value_type;
typedef ListNode<T> node_type;
typedef ListIterator<T> iterator;
typedef ListConstIterator<T> const_iterator;
// Creates an empty List<T> attached to a JsonBuffer.
// The JsonBuffer allows to allocate new nodes.
// When buffer is NULL, the List is not able to grow and success() returns
// false. This is used to identify bad memory allocations and parsing
// failures.
explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {}
// Returns true if the object is valid
// Would return false in the following situation:
// - the memory allocation failed (StaticJsonBuffer was too small)
// - the JSON parsing failed
bool success() const { return _buffer != NULL; }
// Returns the numbers of elements in the list.
// For a JsonObject, it would return the number of key-value pairs
int size() const;
iterator begin() { return iterator(_firstNode); }
iterator end() { return iterator(NULL); }
const_iterator begin() const { return const_iterator(_firstNode); }
const_iterator end() const { return const_iterator(NULL); }
protected:
node_type *createNode() {
if (!_buffer) return NULL;
void *ptr = _buffer->alloc(sizeof(node_type));
return ptr ? new (ptr) node_type() : NULL;
}
void addNode(node_type *nodeToAdd) {
if (_firstNode) {
node_type *lastNode = _firstNode;
while (lastNode->next) lastNode = lastNode->next;
lastNode->next = nodeToAdd;
} else {
_firstNode = nodeToAdd;
}
}
void removeNode(node_type *nodeToRemove);
JsonBuffer *_buffer;
node_type *_firstNode;
};
}
}

View File

@ -0,0 +1,40 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "ListNode.hpp"
namespace ArduinoJson {
namespace Internals {
// A read-only forward itertor for List<T>
template <typename T>
class ListConstIterator {
public:
explicit ListConstIterator(const ListNode<T> *node = NULL) : _node(node) {}
const T &operator*() const { return _node->content; }
const T *operator->() { return &_node->content; }
bool operator==(const ListConstIterator<T> &other) const {
return _node == other._node;
}
bool operator!=(const ListConstIterator<T> &other) const {
return _node != other._node;
}
ListConstIterator<T> &operator++() {
if (_node) _node = _node->next;
return *this;
}
private:
const ListNode<T> *_node;
};
}
}

View File

@ -0,0 +1,40 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "ListNode.hpp"
namespace ArduinoJson {
namespace Internals {
// A read-write forward iterator for List<T>
template <typename T>
class ListIterator {
public:
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
T &operator*() const { return _node->content; }
T *operator->() { return &_node->content; }
bool operator==(const ListIterator<T> &other) const {
return _node == other._node;
}
bool operator!=(const ListIterator<T> &other) const {
return _node != other._node;
}
ListIterator<T> &operator++() {
if (_node) _node = _node->next;
return *this;
}
private:
ListNode<T> *_node;
};
}
}

View File

@ -0,0 +1,24 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include <stddef.h> // for NULL
namespace ArduinoJson {
namespace Internals {
// A node for a singly-linked list.
// Used by List<T> and its iterators.
template <typename T>
struct ListNode {
ListNode() : next(NULL) {}
ListNode<T>* next;
T content;
};
}
}

View File

@ -0,0 +1,19 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#ifdef ARDUINO
// Declares the placement new as in <new>.
// This is required for Arduino IDE because it doesn't include the <new> header.
inline void *operator new(size_t, void *p) throw() { return p; }
#else
#include <new>
#endif

View File

@ -0,0 +1,46 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "IndentedPrint.hpp"
namespace ArduinoJson {
namespace Internals {
// Converts a compact JSON string into an indented one.
class Prettyfier : public Print {
public:
explicit Prettyfier(IndentedPrint& p) : _sink(p) {
_previousChar = 0;
_inString = false;
}
virtual size_t write(uint8_t);
private:
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
bool inEmptyBlock() { return _previousChar == '{' || _previousChar == '['; }
size_t handleStringChar(uint8_t);
size_t handleMarkupChar(uint8_t);
size_t handleBlockClose(uint8_t);
size_t handleBlockOpen(uint8_t);
size_t handleColumn();
size_t handleComma();
size_t handleQuoteOpen();
size_t handleNormalChar(uint8_t);
size_t indentIfNeeded();
size_t unindentIfNeeded();
uint8_t _previousChar;
IndentedPrint& _sink;
bool _inString;
};
}
}

View File

@ -0,0 +1,29 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
// An helper class to print and extract doubly-quoted strings
class QuotedString {
public:
// Writes a doubly-quote string to a Print implementation.
// It adds the double quotes (") at the beginning and the end of the string.
// It escapes the special characters as required by the JSON specifications.
static size_t printTo(const char *, Print &);
// Reads a doubly-quoted string from a buffer.
// It removes the double quotes (").
// It unescapes the special character as required by the JSON specification,
// with the exception of the Unicode characters (\u0000).
static char *extractFrom(char *input, char **end);
};
}
}

View File

@ -0,0 +1,34 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
namespace ArduinoJson {
namespace Internals {
// A type that is meant to be used by reference only (JsonArray and JsonObject)
class ReferenceType {
public:
bool operator==(const ReferenceType& other) const {
// two JsonArray are equal if they are the same instance
// (we don't compare the content)
return this == &other;
}
bool operator!=(const ReferenceType& other) const { return this != &other; }
protected:
ReferenceType() {}
private:
// copy constructor is private
ReferenceType(const ReferenceType&);
// copy operator is private
ReferenceType& operator=(const ReferenceType&);
};
}
}

View File

@ -0,0 +1,30 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
// A Print implementation that allows to write in a char[]
class StringBuilder : public Print {
public:
StringBuilder(char *buf, int size)
: buffer(buf), capacity(size - 1), length(0) {
buffer[0] = '\0';
}
virtual size_t write(uint8_t c);
private:
char *buffer;
int capacity;
int length;
};
}
}

View File

@ -0,0 +1,88 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "JsonVariant.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
(sizeof(JsonArray) + (NUMBER_OF_ELEMENTS) * sizeof(JsonArray::node_type))
namespace ArduinoJson {
// Forward declarations
class JsonObject;
class JsonBuffer;
// An array of JsonVariant.
//
// The constructor is private, instances must be created via
// JsonBuffer::createArray() or JsonBuffer::parseArray().
// A JsonArray can be serialized to a JSON string via JsonArray::printTo().
// It can also be deserialized from a JSON string via JsonBuffer::parseArray().
class JsonArray : public Internals::JsonPrintable<JsonArray>,
public Internals::ReferenceType,
public Internals::List<JsonVariant> {
// JsonBuffer is a friend because it needs to call the private constructor.
friend class JsonBuffer;
public:
// Returns the JsonVariant at the specified index (synonym for operator[])
JsonVariant &at(int index) const;
// Returns the JsonVariant at the specified index (synonym for at())
JsonVariant &operator[](int index) const { return at(index); }
// Adds an uninitialized JsonVariant at the end of the array.
// Return a reference or JsonVariant::invalid() if allocation fails.
JsonVariant &add();
// Adds the specified value at the end of the array.
template <typename T>
void add(T value) {
add().set(value);
}
// Adds the specified double value at the end of the array.
// The value will be printed with the specified number of decimal digits.
void add(double value, uint8_t decimals) { add().set(value, decimals); }
// Adds a reference to the specified JsonArray at the end of the array.
void add(JsonArray &array) { add().set(array); }
// Adds a reference to the specified JsonObject at the end of the array.
void add(JsonObject &obejct) { add().set(obejct); }
// Creates a JsonArray and adds a reference at the end of the array.
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
JsonArray &createNestedArray();
// Creates a JsonObject and adds a reference at the end of the array.
// It's a shortcut for JsonBuffer::createObject() and JsonArray::add()
JsonObject &createNestedObject();
// Returns a reference an invalid JsonArray.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonArray &invalid() { return _invalid; }
// Serialize the array to the specified JsonWriter.
void writeTo(Internals::JsonWriter &writer) const;
private:
// Create an empty JsonArray attached to the specified JsonBuffer.
explicit JsonArray(JsonBuffer *buffer)
: Internals::List<JsonVariant>(buffer) {}
// The instance returned by JsonArray::invalid()
static JsonArray _invalid;
};
}

View File

@ -0,0 +1,81 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t
namespace ArduinoJson {
class JsonArray;
class JsonObject;
// Entry point for using the library.
//
// Handle the memory management (done in derived classes) and calls the parser.
// This abstract class is implemented by StaticJsonBuffer which implements a
// fixed memory allocation.
class JsonBuffer {
public:
// CAUTION: NO VIRTUAL DESTRUCTOR!
// If we add a virtual constructor the Arduino compiler will add malloc() and
// free() to the binary, adding 706 useless bytes.
// virtual ~JsonBuffer() {}
// Allocates an empty JsonArray.
//
// Returns a reference to the new JsonArray or JsonArray::invalid() if the
// allocation fails.
JsonArray &createArray();
// Allocates an empty JsonObject.
//
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
// allocation fails.
JsonObject &createObject();
// Allocates and populate a JsonArray from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
// writable
// because the parser will insert null-terminators and replace escaped chars.
//
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
//
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
// allocation fails.
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
// Allocates and populate a JsonObject from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
// writable
// because the parser will insert null-terminators and replace escaped chars.
//
// The second argument set the nesting limit (see comment on DEFAULT_LIMIT)
//
// Returns a reference to the new JsonObject or JsonObject::invalid() if the
// allocation fails.
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
// Allocates n bytes in the JsonBuffer.
// Return a pointer to the allocated memory or NULL if allocation fails.
virtual void *alloc(size_t size) = 0;
// Default value of nesting limit of parseArray() and parseObject().
//
// The nesting limit is a contain on the level of nesting allowed in the JSON
// string.
// If set to 0, only a flat array or objects can be parsed.
// If set to 1, the object can contain nested arrays or objects but only 1
// level deep.
// And bigger values will allow more level of nesting.
//
// The purpose of this feature is to prevent stack overflow that could lead to
// a security risk.
static const uint8_t DEFAULT_LIMIT = 10;
};
}

View File

@ -0,0 +1,105 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
#include "Internals/ReferenceType.hpp"
#include "JsonPair.hpp"
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
(sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type))
namespace ArduinoJson {
// Forward declarations
class JsonArray;
class JsonBuffer;
// A dictionary of JsonVariant indexed by string (char*)
//
// The constructor is private, instances must be created via
// JsonBuffer::createObject() or JsonBuffer::parseObject().
// A JsonObject can be serialized to a JSON string via JsonObject::printTo().
// It can also be deserialized from a JSON string via JsonBuffer::parseObject().
class JsonObject : public Internals::JsonPrintable<JsonObject>,
public Internals::ReferenceType,
public Internals::List<JsonPair> {
// JsonBuffer is a friend because it needs to call the private constructor.
friend class JsonBuffer;
public:
typedef const char *key_type;
typedef JsonPair value_type;
// Gets the JsonVariant associated with the specified key.
// Returns a reference or JsonVariant::invalid() if not found.
JsonVariant &at(key_type key);
// Gets the JsonVariant associated with the specified key.
// Returns a constant reference or JsonVariant::invalid() if not found.
const JsonVariant &at(key_type key) const;
// Gets or create the JsonVariant associated with the specified key.
// Returns a reference or JsonVariant::invalid() if allocation failed.
JsonVariant &operator[](key_type key);
// Gets the JsonVariant associated with the specified key.
// Returns a constant reference or JsonVariant::invalid() if not found.
const JsonVariant &operator[](key_type key) const { return at(key); }
// Adds an uninitialized JsonVariant associated with the specified key.
// Return a reference or JsonVariant::invalid() if allocation fails.
JsonVariant &add(key_type key) { return (*this)[key]; }
// Adds the specified key with the specified value.
template <typename T>
void add(key_type key, T value) {
add(key).set(value);
}
// Adds the specified key with a reference to the specified JsonArray.
void add(key_type key, JsonArray &array) { add(key).set(array); }
// Adds the specified key with a reference to the specified JsonObject.
void add(key_type key, JsonObject &object) { add(key).set(object); }
// Creates and adds a JsonArray.
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
JsonArray &createNestedArray(key_type key);
// Creates and adds a JsonObject.
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
JsonObject &createNestedObject(key_type key);
// Tells weither the specified key is present and associated with a value.
bool containsKey(key_type key) const { return at(key).success(); }
// Removes the specified key and the associated value.
void remove(key_type key);
// Returns a reference an invalid JsonObject.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonObject &invalid() { return _invalid; }
// Serialize the object to the specified JsonWriter
void writeTo(Internals::JsonWriter &writer) const;
private:
// Create an empty JsonArray attached to the specified JsonBuffer.
explicit JsonObject(JsonBuffer *buffer) : Internals::List<JsonPair>(buffer) {}
// Returns the list node that matches the specified key.
node_type *getNodeAt(key_type key) const;
// The instance returned by JsonObject::invalid()
static JsonObject _invalid;
};
}

View File

@ -0,0 +1,18 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "JsonVariant.hpp"
namespace ArduinoJson {
// A key value pair for JsonObject.
struct JsonPair {
const char* key;
JsonVariant value;
};
}

View File

@ -0,0 +1,286 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "Internals/JsonPrintable.hpp"
#include "Internals/JsonVariantContent.hpp"
#include "Internals/JsonVariantType.hpp"
namespace ArduinoJson {
// Forward declarations.
class JsonArray;
class JsonObject;
// A variant that can be a any value serializable to a JSON value.
//
// It can be set to:
// - a boolean
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a JsonArray or JsonObject
class JsonVariant : public Internals::JsonPrintable<JsonVariant> {
public:
// Creates an uninitialized JsonVariant
JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
// Initializes a JsonVariant with the specified value.
template <typename T>
explicit JsonVariant(T value) {
set(value);
}
// Tells weither the variant is valid.
bool success() const {
return _type != Internals::JSON_INVALID &&
_type != Internals::JSON_UNDEFINED;
}
// Sets the variant to a boolean value.
// It will be serialized as "true" or "false" in JSON.
void set(bool value);
// Sets the variant to a floating point value.
// The second argument specifies the number of decimal digits to write in
// the JSON string.
void set(double value, uint8_t decimals = 2);
// Sets the variant to be an integer value.
void set(signed long value);
void set(signed char value) { set(static_cast<long>(value)); }
void set(signed int value) { set(static_cast<long>(value)); }
void set(signed short value) { set(static_cast<long>(value)); }
void set(unsigned char value) { set(static_cast<long>(value)); }
void set(unsigned int value) { set(static_cast<long>(value)); }
void set(unsigned long value) { set(static_cast<long>(value)); }
void set(unsigned short value) { set(static_cast<long>(value)); }
// Sets the variant to be a string.
void set(const char *value);
// Sets the variant to be a reference to an array.
void set(JsonArray &array);
// Sets the variant to be a reference to an object.
void set(JsonObject &object);
// Sets the variant to the specified value.
template <typename T>
JsonVariant &operator=(T value) {
set(value);
return *this;
}
// Sets the variant to be a reference to an array.
JsonVariant &operator=(JsonArray &array) {
set(array);
return *this;
}
// Sets the variant to be a reference to an object.
JsonVariant &operator=(JsonObject &object) {
set(object);
return *this;
}
// Gets the variant as a boolean value.
// Returns false if the variant is not a boolean value.
operator bool() const;
// Gets the variant as a floating-point value.
// Returns 0.0 if the variant is not a floating-point value
operator double() const;
operator float() const { return static_cast<float>(as<double>()); }
// Gets the variant as an integer value.
// Returns 0 if the variant is not an integer value.
operator signed long() const;
operator signed char() const { return cast_long_to<signed char>(); }
operator signed int() const { return cast_long_to<signed int>(); }
operator signed short() const { return cast_long_to<signed short>(); }
operator unsigned char() const { return cast_long_to<unsigned char>(); }
operator unsigned int() const { return cast_long_to<unsigned int>(); }
operator unsigned long() const { return cast_long_to<unsigned long>(); }
operator unsigned short() const { return cast_long_to<unsigned short>(); }
// Gets the variant as a string.
// Returns NULL if variant is not a string.
operator const char *() const;
const char *asString() const { return as<const char *>(); }
// Gets the variant as an array.
// Returns a reference to the JsonArray or JsonArray::invalid() if the variant
// is not an array.
operator JsonArray &() const;
JsonArray &asArray() const { return as<JsonArray &>(); }
// Gets the variant as an object.
// Returns a reference to the JsonObject or JsonObject::invalid() if the
// variant is not an object.
operator JsonObject &() const;
JsonObject &asObject() const { return as<JsonObject &>(); }
// Get the variant as the specified type.
// See cast operators for details.
template <typename T>
T as() const {
return static_cast<T>(*this);
}
// Tells weither the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
template <typename T>
bool is() const {
return false;
}
// Returns an invalid variant.
// This is meant to replace a NULL pointer.
static JsonVariant &invalid() { return _invalid; }
// Serialize the variant to a JsonWriter
void writeTo(Internals::JsonWriter &writer) const;
// Mimics an array or an object.
// Returns the size of the array or object if the variant has that type.
// Returns 0 if the variant is neither an array nor an object
size_t size() const;
// Mimics an array.
// Returns the element at specified index if the variant is an array.
// Returns JsonVariant::invalid() if the variant is not an array.
JsonVariant &operator[](int index);
// Mimics an object.
// Returns the value associated with the specified key if the variant is an
// object.
// Return JsonVariant::invalid() if the variant is not an object.
JsonVariant &operator[](const char *key);
private:
// Special constructor used only to create _invalid.
explicit JsonVariant(Internals::JsonVariantType type) : _type(type) {}
// Helper for interger cast operators
template <typename T>
T cast_long_to() const {
return static_cast<T>(as<long>());
}
// The current type of the variant
Internals::JsonVariantType _type;
// The various alternatives for the value of the variant.
Internals::JsonVariantContent _content;
// The instance returned by JsonVariant::invalid()
static JsonVariant _invalid;
};
template <>
inline bool JsonVariant::is<long>() const {
return _type == Internals::JSON_LONG;
}
template <>
inline bool JsonVariant::is<double>() const {
return _type >= Internals::JSON_DOUBLE_0_DECIMALS;
}
template <>
inline bool JsonVariant::is<bool>() const {
return _type == Internals::JSON_BOOLEAN;
}
template <>
inline bool JsonVariant::is<const char *>() const {
return _type == Internals::JSON_STRING;
}
template <>
inline bool JsonVariant::is<JsonArray &>() const {
return _type == Internals::JSON_ARRAY;
}
template <>
inline bool JsonVariant::is<const JsonArray &>() const {
return _type == Internals::JSON_ARRAY;
}
template <>
inline bool JsonVariant::is<JsonObject &>() const {
return _type == Internals::JSON_OBJECT;
}
template <>
inline bool JsonVariant::is<const JsonObject &>() const {
return _type == Internals::JSON_OBJECT;
}
template <typename T>
inline bool operator==(const JsonVariant &left, T right) {
return left.as<T>() == right;
}
template <typename T>
inline bool operator==(T left, const JsonVariant &right) {
return left == right.as<T>();
}
template <typename T>
inline bool operator!=(const JsonVariant &left, T right) {
return left.as<T>() != right;
}
template <typename T>
inline bool operator!=(T left, const JsonVariant &right) {
return left != right.as<T>();
}
template <typename T>
inline bool operator<=(const JsonVariant &left, T right) {
return left.as<T>() <= right;
}
template <typename T>
inline bool operator<=(T left, const JsonVariant &right) {
return left <= right.as<T>();
}
template <typename T>
inline bool operator>=(const JsonVariant &left, T right) {
return left.as<T>() >= right;
}
template <typename T>
inline bool operator>=(T left, const JsonVariant &right) {
return left >= right.as<T>();
}
template <typename T>
inline bool operator<(const JsonVariant &left, T right) {
return left.as<T>() < right;
}
template <typename T>
inline bool operator<(T left, const JsonVariant &right) {
return left < right.as<T>();
}
template <typename T>
inline bool operator>(const JsonVariant &left, T right) {
return left.as<T>() > right;
}
template <typename T>
inline bool operator>(T left, const JsonVariant &right) {
return left > right.as<T>();
}
}

View File

@ -0,0 +1,36 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "JsonBuffer.hpp"
namespace ArduinoJson {
// Implements a JsonBuffer with fixed memory allocation.
// The template paramenter CAPACITY specifies the capacity of the buffer in
// bytes.
template <size_t CAPACITY>
class StaticJsonBuffer : public JsonBuffer {
public:
explicit StaticJsonBuffer() : _size(0) {}
size_t capacity() const { return CAPACITY; }
size_t size() const { return _size; }
protected:
virtual void* alloc(size_t size) {
if (_size + size > CAPACITY) return NULL;
void* p = &_buffer[_size];
_size += size;
return p;
}
private:
uint8_t _buffer[CAPACITY];
size_t _size;
};
}

View File

@ -1,10 +1,14 @@
JsonParser KEYWORD1
JsonArray KEYWORD1
JsonHashTable KEYWORD1
getArray KEYWORD2
getBool KEYWORD2
getDouble KEYWORD2
getHashTableKEYWORD2
getLong KEYWORD2
JsonObject KEYWORD1
JsonVariant KEYWORD1
StaticJsonBuffer KEYWORD1
add KEYWORD2
createArray KEYWORD2
createNestedArray KEYWORD2
createNestedObject KEYWORD2
createObject KEYWORD2
parseArray KEYWORD2
parseHashTable KEYWORD2
parseObject KEYWORD2
prettyPrintTo KEYWORD2
printTo KEYWORD2
success KEYWORD2

17
library.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "Json",
"keywords": "json, rest, http, web",
"description": "An elegant and efficient JSON library for embedded systems",
"repository":
{
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"authors":
{
"name": "Benoit Blanchon",
"url": "http://blog.benoitblanchon.fr"
},
"frameworks": "arduino",
"platforms": "atmelavr"
}

8
library.properties Normal file
View File

@ -0,0 +1,8 @@
name=ArduinoJson
version=4.0
author=Benoit Blanchon <http://blog.benoitblanchon.fr/>
maintainer=Benoit Blanchon <http://blog.benoitblanchon.fr/>
sentence=An efficient and elegant JSON library for Arduino
paragraph=Supports JSON parsing and formatting. Uses fixed memory allocation.
url=https://github.com/bblanchon/ArduinoJson
architectures=*

View File

@ -0,0 +1,22 @@
#!/bin/bash
ZIP="C:\Program Files\7-Zip\7z.exe"
TAG=$(git describe)
OUTPUT="ArduinoJson-$TAG.zip"
cd ../..
# remove existing file
rm -f $OUTPUT
# create zip
"$ZIP" a $OUTPUT \
ArduinoJson/CHANGELOG.md \
ArduinoJson/doc \
ArduinoJson/examples \
ArduinoJson/include \
ArduinoJson/keywords.txt \
ArduinoJson/library.properties \
ArduinoJson/LICENSE.md \
ArduinoJson/README.md \
ArduinoJson/src

5
scripts/cpplint.sh Executable file
View File

@ -0,0 +1,5 @@
CPPLINT="python third-party/cpplint/cpplint.py"
FLAGS="--filter=-runtime/printf,-runtime/int,-readability/todo,-build/namespace,-runtime/references,-readability/streams"
cd ..
$CPPLINT $FLAGS $(find include src test -regex ".*\.[hc]pp$")

29
scripts/create-build-envs.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash
export PATH="$PATH:/Applications/CMake.app/Contents/bin/"
cd $(dirname $0)/..
ROOT=$(pwd)
mkdir "build"
cd build
BUILD=$(pwd)
build-env()
{
cd $BUILD
mkdir "$1"
cd "$1"
cmake "$ROOT" -G "$2"
}
if [[ $(uname) == MINGW* ]]
then
build-env "Make" "MinGW Makefiles"
build-env "SublimeText" "Sublime Text 2 - MinGW Makefiles"
build-env "VisualStudio" "Visual Studio 12 2013"
else
build-env "SublimeText" "Sublime Text 2 - Unix Makefiles"
build-env "Make" "Unix Makefiles"
build-env "Xcode" "Xcode"
fi

7
scripts/format-code.sh Executable file
View File

@ -0,0 +1,7 @@
cd ..
FILES=$(find include src test -regex ".*\.[ch]pp$")
clang-format -style=Google -i $FILES
# insert newline at end of file
sed -i -e '$a\' $FILES

44
scripts/run-tests.sh Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
FILE=../bin/ArduinoJsonTests.exe
MD5=""
file_changed() {
[[ ! -f "$FILE" ]] && return 1
NEW_MD5=$(md5sum $FILE)
[[ "$MD5" == "$NEW_MD5" ]] && return 1
MD5=$NEW_MD5
return 0
}
test_succeed() {
echo -en "\007"{,}
}
test_failed() {
echo -en "\007"{,,,,,,,,,,,}
}
run_tests() {
$FILE
case $? in
0)
test_succeed
;;
1)
test_failed
;;
esac
}
while true
do
if file_changed
then
run_tests
else
sleep 2
fi
done

35
src/Arduino/Print.cpp Normal file
View File

@ -0,0 +1,35 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#ifndef ARDUINO
#include "../../include/ArduinoJson/Arduino/Print.hpp"
#include <stdio.h> // for sprintf
size_t Print::print(const char s[]) {
size_t n = 0;
while (*s) {
n += write(*s++);
}
return n;
}
size_t Print::print(double value, int digits) {
char tmp[32];
sprintf(tmp, "%.*f", digits, value);
return print(tmp);
}
size_t Print::print(long value) {
char tmp[32];
sprintf(tmp, "%ld", value);
return print(tmp);
}
size_t Print::println() { return write('\r') + write('\n'); }
#endif

13
src/ArduinoJson.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// About this file
// ---------------
// This file is here to please the Arduino IDE. It must be present in the src/
// for the IDE to find it. Feel free to ignore this file if your working in
// another environment
#include "../include/ArduinoJson.h"

42
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,42 @@
file(GLOB_RECURSE INC_FILES ../include/*.hpp)
file(GLOB_RECURSE SRC_FILES *.cpp)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_definitions(
-fno-exceptions
-pedantic
-Wall
-Wcast-align
-Wcast-qual
-Wconversion
-Wctor-dtor-privacy
-Wdisabled-optimization
-Werror
-Wextra
-Wformat=2
-Winit-self
-Wmissing-include-dirs
-Wno-parentheses
-Wno-sign-conversion
-Wno-unused
-Wno-variadic-macros
-Wold-style-cast
-Woverloaded-virtual
-Wredundant-decls
-Wshadow
-Wsign-promo
-Wstrict-overflow=5
-Wundef
)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU)")
add_definitions(
-Wlogical-op
-Wnoexcept
-Wstrict-null-sentinel
)
endif()
add_library(ArduinoJson ${SRC_FILES} ${INC_FILES})

View File

@ -0,0 +1,29 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include "../../include/ArduinoJson/Internals/IndentedPrint.hpp"
using namespace ArduinoJson::Internals;
size_t IndentedPrint::write(uint8_t c) {
size_t n = 0;
if (isNewLine) n += writeTabs();
n += sink->write(c);
isNewLine = c == '\n';
return n;
}
inline size_t IndentedPrint::writeTabs() {
size_t n = 0;
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
return n;
}

View File

@ -0,0 +1,197 @@
// Copyright Benoit Blanchon 2014
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#include "../../include/ArduinoJson/Internals/JsonParser.hpp"
#include <stdlib.h> // for strtol, strtod
#include <ctype.h>
#include "../../include/ArduinoJson/Internals/QuotedString.hpp"
#include "../../include/ArduinoJson/JsonArray.hpp"
#include "../../include/ArduinoJson/JsonBuffer.hpp"
#include "../../include/ArduinoJson/JsonObject.hpp"
using namespace ArduinoJson;
using namespace ArduinoJson::Internals;
void JsonParser::skipSpaces() {
while (isspace(*_ptr)) _ptr++;
}
bool JsonParser::skip(char charToSkip) {
skipSpaces();
if (*_ptr != charToSkip) return false;
_ptr++;
skipSpaces();
return true;
}
bool JsonParser::skip(const char *wordToSkip) {
const char *charToSkip = wordToSkip;
while (*charToSkip && *_ptr == *charToSkip) {
charToSkip++;
_ptr++;
}
return *charToSkip == '\0';
}
void JsonParser::parseAnythingTo(JsonVariant &destination) {
if (_nestingLimit == 0) return;
_nestingLimit--;
skipSpaces();
switch (*_ptr) {
case '[':
destination = parseArray();
break;
case '{':
destination = parseObject();
break;
case 't':
case 'f':
parseBooleanTo(destination);
break;
case '-':
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
parseNumberTo(destination);
break;
case 'n':
parseNullTo(destination);
break;
case '\'':
case '\"':
destination = parseString();
break;
}
_nestingLimit++;
}
JsonArray &JsonParser::parseArray() {
// Create an empty array
JsonArray &array = _buffer->createArray();
// Check opening braket
if (!skip('[')) goto ERROR_MISSING_BRACKET;
if (skip(']')) goto SUCCESS_EMPTY_ARRAY;
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant &value = array.add();
parseAnythingTo(value);
if (!value.success()) goto ERROR_INVALID_VALUE;
// 2 - More values?
if (skip(']')) goto SUCCES_NON_EMPTY_ARRAY;
if (!skip(',')) goto ERROR_MISSING_COMMA;
}
SUCCESS_EMPTY_ARRAY:
SUCCES_NON_EMPTY_ARRAY:
return array;
ERROR_INVALID_VALUE:
ERROR_MISSING_BRACKET:
ERROR_MISSING_COMMA:
return JsonArray::invalid();
}
JsonObject &JsonParser::parseObject() {
// Create an empty object
JsonObject &object = _buffer->createObject();
// Check opening brace
if (!skip('{')) goto ERROR_MISSING_BRACE;
if (skip('}')) goto SUCCESS_EMPTY_OBJECT;
// Read each key value pair
for (;;) {
// 1 - Parse key
const char *key = parseString();
if (!key) goto ERROR_INVALID_KEY;
if (!skip(':')) goto ERROR_MISSING_COLON;
// 2 - Parse value
JsonVariant &value = object.add(key);
parseAnythingTo(value);
if (!value.success()) goto ERROR_INVALID_VALUE;
// 3 - More keys/values?
if (skip('}')) goto SUCCESS_NON_EMPTY_OBJECT;
if (!skip(',')) goto ERROR_MISSING_COMMA;
}
SUCCESS_EMPTY_OBJECT:
SUCCESS_NON_EMPTY_OBJECT:
return object;
ERROR_INVALID_KEY:
ERROR_INVALID_VALUE:
ERROR_MISSING_BRACE:
ERROR_MISSING_COLON:
ERROR_MISSING_COMMA:
return JsonObject::invalid();
}
void JsonParser::parseBooleanTo(JsonVariant &destination) {
if (skip("true"))
destination = true;
else if (skip("false"))
destination = false;
else
destination = JsonVariant::invalid();
}
void JsonParser::parseNumberTo(JsonVariant &destination) {
char *endOfLong;
long longValue = strtol(_ptr, &endOfLong, 10);
char stopChar = *endOfLong;
// Could it be a floating point value?
bool couldBeFloat = stopChar == '.' || stopChar == 'e' || stopChar == 'E';
if (couldBeFloat) {
// Yes => parse it as a double
double doubleValue = strtod(_ptr, &_ptr);
// Count the decimal digits
uint8_t decimals = static_cast<uint8_t>(_ptr - endOfLong - 1);
// Set the variant as a double
destination.set(doubleValue, decimals);
} else {
// No => set the variant as a long
_ptr = endOfLong;
destination = longValue;
}
}
void JsonParser::parseNullTo(JsonVariant &destination) {
const char *NULL_STRING = NULL;
if (skip("null"))
destination = NULL_STRING;
else
destination = JsonVariant::invalid();
}
const char *JsonParser::parseString() {
return QuotedString::extractFrom(_ptr, &_ptr);
}

Some files were not shown because too many files have changed in this diff Show More