Compare commits

..

55 Commits
v3.1 ... v3.3

Author SHA1 Message Date
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
27 changed files with 862 additions and 66 deletions

13
BuildArduinoPackage.sh Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
ZIP="C:\Program Files\7-Zip\7z.exe"
TAG=$(git describe)
OUTPUT="ArduinoJson-$TAG.zip"
cd ..
INPUT=$(find ArduinoJson -regex ".*\.\(cpp\|h\|md\|txt\|ino\)$" -not -regex ".*Tests/.*")
rm -f $OUTPUT
"$ZIP" a $OUTPUT $INPUT

View File

@ -1,6 +1,23 @@
Arduino JSON: change log
========================
v3.3
----
* Added indented output for the JSON generator, 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
----

View File

@ -6,7 +6,10 @@
// This file is here to help the Arduino IDE find the .cpp files
#include "JsonGenerator/EscapedString.cpp"
#include "JsonGenerator/IndentedPrint.cpp"
#include "JsonGenerator/JsonArrayBase.cpp"
#include "JsonGenerator/JsonObjectBase.cpp"
#include "JsonGenerator/JsonValue.cpp"
#include "JsonGenerator/JsonPrettyPrint.cpp"
#include "JsonGenerator/JsonPrintable.cpp"
#include "JsonGenerator/StringBuilder.cpp"

View File

@ -0,0 +1,45 @@
#include "IndentedPrint.h"
using namespace ArduinoJson::Generator;
void IndentedPrint::indent()
{
if (level < MAX_LEVEL)
level++;
}
void IndentedPrint::unindent()
{
if (level > 0)
level--;
}
void IndentedPrint::setTabSize(uint8_t n)
{
if (n < MAX_TAB_SIZE)
tabSize = n;
}
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,53 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "Print.h"
namespace ArduinoJson
{
namespace Generator
{
// 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:
IndentedPrint(Print& p)
: sink(p)
{
level = 0;
tabSize = 2;
isNewLine = true;
}
virtual size_t write(uint8_t);
// Adds one level of indentation
void indent();
// Removes one level of indentation
void unindent();
// Set the number of space printed for each level of indentation
void setTabSize(uint8_t n);
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

@ -6,6 +6,7 @@
#pragma once
#include "JsonPrintable.h"
#include "JsonValue.h"
namespace ArduinoJson
{
@ -20,12 +21,34 @@ namespace ArduinoJson
}
template<typename T>
void add(T value)
void add(const Printable& value)
{
if (count >= capacity) return;
addIfPossible<const Printable&>(value);
}
items[count++] = value;
void add(bool value)
{
addIfPossible<bool>(value);
}
void add(int value)
{
addIfPossible<long>(value);
}
void add(long value)
{
addIfPossible<long>(value);
}
void add(double value)
{
addIfPossible<double>(value);
}
void add(const char* value)
{
addIfPossible<const char*>(value);
}
template<int DIGITS>
@ -44,6 +67,13 @@ namespace ArduinoJson
private:
JsonValue* items;
int capacity, count;
template<typename T>
void addIfPossible(T value)
{
if (count < capacity)
items[count++] = value;
}
};
}
}

View File

@ -12,6 +12,8 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="EscapedString.h" />
<ClInclude Include="IndentedPrint.h" />
<ClInclude Include="JsonPrettyPrint.h" />
<ClInclude Include="JsonArray.h" />
<ClInclude Include="JsonArrayBase.h" />
<ClInclude Include="JsonObject.h" />
@ -24,8 +26,11 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="EscapedString.cpp" />
<ClCompile Include="IndentedPrint.cpp" />
<ClCompile Include="JsonPrettyPrint.cpp" />
<ClCompile Include="JsonArrayBase.cpp" />
<ClCompile Include="JsonObjectBase.cpp" />
<ClCompile Include="JsonPrintable.cpp" />
<ClCompile Include="JsonValue.cpp" />
<ClCompile Include="Print.cpp" />
<ClCompile Include="StringBuilder.cpp" />

View File

@ -45,6 +45,12 @@
<ClInclude Include="JsonObject.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IndentedPrint.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="JsonPrettyPrint.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="EscapedString.cpp">
@ -65,5 +71,14 @@
<ClCompile Include="JsonObjectBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="IndentedPrint.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonPrettyPrint.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonPrintable.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -6,6 +6,7 @@
#pragma once
#include "JsonPrintable.h"
#include "JsonValue.h"
#include "EscapedString.h"
namespace ArduinoJson

View File

@ -0,0 +1,97 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonPrettyPrint.h"
using namespace ArduinoJson::Generator;
size_t JsonPrettyPrint::write(uint8_t c)
{
size_t n = inString ? handleStringChar(c) : handleMarkupChar(c);
previousChar = c;
return n;
}
inline size_t JsonPrettyPrint::handleStringChar(uint8_t c)
{
bool isQuote = c == '"' && previousChar != '\\';
if (isQuote) inString = false;
return sink.write(c);
}
inline size_t JsonPrettyPrint::handleMarkupChar(uint8_t c)
{
switch (c)
{
case '{':
case '[':
return handleBlockOpen(c);
case '}':
case ']':
return handleBlockClose(c);
case ':':
return handleColumn();
case ',':
return handleComma();
case '"':
return handleQuoteOpen();
default:
return handleNormalChar(c);
}
}
inline size_t JsonPrettyPrint::handleBlockOpen(uint8_t c)
{
return indentIfNeeded() + sink.write(c);
}
inline size_t JsonPrettyPrint::handleBlockClose(uint8_t c)
{
return unindentIfNeeded() + sink.write(c);
}
inline size_t JsonPrettyPrint::handleColumn()
{
return sink.write(':') + sink.write(' ');
}
inline size_t JsonPrettyPrint::handleComma()
{
return sink.write(',') + sink.println();
}
inline size_t JsonPrettyPrint::handleQuoteOpen()
{
inString = true;
return indentIfNeeded() + sink.write('"');
}
inline size_t JsonPrettyPrint::handleNormalChar(uint8_t c)
{
return indentIfNeeded() + sink.write(c);
}
size_t JsonPrettyPrint::indentIfNeeded()
{
if (!inEmptyBlock()) return 0;
sink.indent();
return sink.println();
}
size_t JsonPrettyPrint::unindentIfNeeded()
{
if (inEmptyBlock()) return 0;
sink.unindent();
return sink.println();
}

View File

@ -0,0 +1,52 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#pragma once
#include "Print.h"
#include "IndentedPrint.h"
namespace ArduinoJson
{
namespace Generator
{
// Converts a compact JSON string into an indented one.
class JsonPrettyPrint : public Print
{
public:
JsonPrettyPrint(IndentedPrint& p)
: sink(p)
{
previousChar = 0;
inString = false;
}
virtual size_t write(uint8_t);
private:
uint8_t previousChar;
IndentedPrint& sink;
bool inString;
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();
};
}
}

View File

@ -0,0 +1,35 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "JsonPrintable.h"
#include "JsonPrettyPrint.h"
#include "StringBuilder.h"
using namespace ArduinoJson::Generator;
using namespace ArduinoJson::Internals;
size_t JsonPrintable::printTo(char* buffer, size_t bufferSize) const
{
StringBuilder sb(buffer, bufferSize);
return printTo(sb);
}
size_t JsonPrintable::prettyPrintTo(char* buffer, size_t bufferSize) const
{
StringBuilder sb(buffer, bufferSize);
return prettyPrintTo(sb);
}
size_t JsonPrintable::prettyPrintTo(IndentedPrint& p) const
{
JsonPrettyPrint prettyPrint(p);
return printTo(prettyPrint);
}
size_t JsonPrintable::prettyPrintTo(Print& p) const
{
IndentedPrint indentedPrint(p);
return prettyPrintTo(indentedPrint);
}

View File

@ -5,27 +5,36 @@
#pragma once
#include "JsonValue.h"
#include "Print.h"
#include "Printable.h"
#include "IndentedPrint.h"
namespace ArduinoJson
{
namespace Generator
{
// Contains methods to generate a JSON string.
// Implemented by both JsonObject and JsonArray
class JsonPrintable : public Printable
{
public:
size_t printTo(char* buffer, size_t bufferSize)
{
using namespace Internals;
StringBuilder sb(buffer, bufferSize);
return printTo(sb);
}
// Generates the compact JSON string and sends it to a Print stream
virtual size_t printTo(Print& p) const = 0;
// Generates the compact JSON string and writes it in a buffer
size_t printTo(char* buffer, size_t bufferSize) const;
// Generates the indented JSON string and sends it to a Print stream
size_t prettyPrintTo(Print& p) const;
// Generates the indented JSON string and sends it to a IndentedPrint stream
// This overload allows a finer control of the output because you can customize
// the IndentedPrint.
size_t prettyPrintTo(IndentedPrint& p) const;
// Generates the indented JSON string and writes it in a buffer
size_t prettyPrintTo(char* buffer, size_t bufferSize) const;
};
}
}

View File

@ -35,7 +35,7 @@ namespace ArduinoJson
content.asLong = value;
}
void operator=(Printable& value)
void operator=(const Printable& value)
{
printToImpl = &printPrintableTo;
content.asPrintable = &value;
@ -89,7 +89,7 @@ namespace ArduinoJson
return content.asLong;
}
operator Printable&()
operator const Printable&()
{
return *content.asPrintable;
}
@ -109,11 +109,11 @@ namespace ArduinoJson
private:
union Content
{
bool asBool;
double asDouble;
long asLong;
Printable* asPrintable;
const char* asString;
bool asBool;
double asDouble;
long asLong;
const Printable* asPrintable;
const char* asString;
};
Content content;

View File

@ -32,4 +32,9 @@ size_t Print::print(long value)
return print(tmp);
}
size_t Print::println()
{
return write('\r') + write('\n');
}
#endif

View File

@ -19,6 +19,7 @@ public:
size_t print(const char[]);
size_t print(double, int = 2);
size_t print(long);
size_t println();
};
#else

View File

@ -15,6 +15,7 @@ Features
* Fixed memory allocation (no malloc)
* Small footprint
* Supports nested objects
* Supports indented output
* Implements Arduino's `Printable interface
* MIT License
@ -101,6 +102,33 @@ or
JsonObject<8> nestedObject;
array.add(nestedObject);
> ##### CAUTION! Nested objects must be in memory
> Calling `add()` makes the `JsonArray` store a pointer to the nested object.
> This is designed to avoid memory duplication.
> But it can only work if the object is in memory when `printTo()` is executed.
> For instance, don't do this:
>
> void addNestedObject()
> {
> JsonObject<2> nestedObject;
> // ...
> array.add(nestedObject); // <- DON'T !!
>
> // array now contains a pointer to a local variable that will be
> // discarded as soon as the function exits
> }
>
> For the same reason, don't do this either:
>
> for( int i=0; i<100; i++)
> {
> JsonObject<2> nestedObject;
> // ...
> array.add(nestedObject); // <- DON'T !!
> }
> // array now contains 100 pointers to the same a local variable
> // that is out of the scope anyway
#### JSON Object
You create a JSON object (ie hash-table/dictionary) with the following line:
@ -150,6 +178,13 @@ Whether you have a `JsonArray` or a `JsonObject`, simply call `printTo()` with t
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 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:
@ -163,7 +198,7 @@ or
> ##### About the Printable interface
> `JsonArray` and `JsonObject` implement Arduino's `Printable` interface.
> This is why you can call `Serial.print()` like in the example above.
> You can do the same with any other implementation of `Print`: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`...
> You can do the same with any other implementation of `Print`: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`, `Wire`...
Memory usage

View File

@ -0,0 +1,73 @@
#include "CppUnitTest.h"
#include "JsonArray.h"
#include "JsonObject.h"
using namespace ArduinoJson::Generator;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace JsonGeneratorTests
{
TEST_CLASS(Issue10)
{
struct Person {
int id;
char name[32];
};
Person persons[2];
public:
TEST_METHOD_INITIALIZE(Initialize)
{
Person boss;
boss.id = 1;
strcpy(boss.name, "Jeff");
Person employee;
employee.id = 2;
strcpy(employee.name, "John");
persons[0] = boss;
persons[1] = employee;
}
TEST_METHOD(WrongWayToAddObjectInAnArray)
{
JsonArray<2> json;
for (int i = 0; i < 2; i++)
{
JsonObject<2> object;
object["id"] = persons[i].id;
object["name"] = persons[i].name;
json.add(object); // <- Adding a reference to a temporary variable
}
char buffer[256];
json.printTo(buffer, sizeof(buffer));
// the same values are repeated, that's normal
Assert::AreEqual("[{\"id\":2,\"name\":\"John\"},{\"id\":2,\"name\":\"John\"}]", buffer);
}
TEST_METHOD(RightWayToAddObjectInAnArray)
{
JsonArray<2> json;
JsonObject<2> object[2];
for (int i = 0; i < 2; i++)
{
object[i]["id"] = persons[i].id;
object[i]["name"] = persons[i].name;
json.add(object[i]);
}
char buffer[256];
json.printTo(buffer, sizeof(buffer));
Assert::AreEqual("[{\"id\":1,\"name\":\"Jeff\"},{\"id\":2,\"name\":\"John\"}]", buffer);
}
};
}

View File

@ -14,7 +14,7 @@ namespace JsonGeneratorTests
{
TEST_CLASS(JsonArrayTests)
{
JsonArray<2> arr;
JsonArray<2> array;
char buffer[256];
public:
@ -26,111 +26,117 @@ namespace JsonGeneratorTests
TEST_METHOD(Null)
{
add((char*)0);
array.add((char*) 0);
outputMustBe("[null]");
}
TEST_METHOD(OneString)
{
add("hello");
array.add("hello");
outputMustBe("[\"hello\"]");
}
TEST_METHOD(TwoStrings)
{
add("hello");
add("world");
array.add("hello");
array.add("world");
outputMustBe("[\"hello\",\"world\"]");
}
TEST_METHOD(OneStringOverCapacity)
{
add("hello");
add("world");
add("lost");
array.add("hello");
array.add("world");
array.add("lost");
outputMustBe("[\"hello\",\"world\"]");
}
TEST_METHOD(OneDoubleDefaultDigits)
{
add(3.14159265358979323846);
array.add(3.14159265358979323846);
outputMustBe("[3.14]");
}
TEST_METHOD(OneDoubleFourDigits)
{
add<4>(3.14159265358979323846);
array.add<4>(3.14159265358979323846);
outputMustBe("[3.1416]");
}
TEST_METHOD(OneInteger)
{
add(1);
array.add(1);
outputMustBe("[1]");
}
TEST_METHOD(TwoIntegers)
{
add(1);
add(2);
array.add(1);
array.add(2);
outputMustBe("[1,2]");
}
TEST_METHOD(OneIntegerOverCapacity)
{
add(1);
add(2);
add(3);
array.add(1);
array.add(2);
array.add(3);
outputMustBe("[1,2]");
}
TEST_METHOD(OneTrue)
{
add(true);
array.add(true);
outputMustBe("[true]");
}
TEST_METHOD(OneFalse)
{
add(false);
array.add(false);
outputMustBe("[false]");
}
TEST_METHOD(TwoBooleans)
{
add(false);
add(true);
array.add(false);
array.add(true);
outputMustBe("[false,true]");
}
TEST_METHOD(OneBooleanOverCapacity)
{
add(false);
add(true);
add(false);
array.add(false);
array.add(true);
array.add(false);
outputMustBe("[false,true]");
}
TEST_METHOD(OneEmptyNestedArray)
{
addNested(JsonArray<1>());
JsonArray<1> nestedArray;
array.add(nestedArray);
outputMustBe("[[]]");
}
TEST_METHOD(OneEmptyNestedHash)
{
addNested(JsonHashTable<1>());
JsonObject<1> nestedObject;
array.add(nestedObject);
outputMustBe("[{}]");
}
@ -139,33 +145,16 @@ namespace JsonGeneratorTests
JsonArray<1> nestedArray;
nestedArray.add(1);
addNested(nestedArray);
array.add(nestedArray);
outputMustBe("[[1]]");
}
private:
void addNested(Printable& value)
{
arr.add<Printable&>(value);
}
template<typename T>
void add(T value)
{
arr.add(value);
}
template<int DIGITS>
void add(double value)
{
arr.add<DIGITS>(value);
}
void outputMustBe(const char* expected)
{
size_t n = arr.printTo(buffer, sizeof(buffer));
size_t n = array.printTo(buffer, sizeof(buffer));
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), n);
}

View File

@ -85,6 +85,10 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="EscapedStringTests.cpp" />
<ClCompile Include="PrettyPrint_Array_Tests.cpp" />
<ClCompile Include="PrettyPrint_Object_Tests.cpp" />
<ClCompile Include="PrettyPrint_String_Tests.cpp" />
<ClCompile Include="Issue10.cpp" />
<ClCompile Include="JsonArrayTests.cpp" />
<ClCompile Include="JsonObject_Indexer_Tests.cpp" />
<ClCompile Include="JsonObject_PrintTo_Tests.cpp" />

View File

@ -36,5 +36,17 @@
<ClCompile Include="JsonValue_Cast_Tests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Issue10.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PrettyPrint_Array_Tests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PrettyPrint_Object_Tests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PrettyPrint_String_Tests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -71,7 +71,7 @@ namespace JsonGeneratorTests
void setValueAndCheckCast(JsonArray<N>& expected)
{
value = expected;
Printable& actual = value;
const Printable& actual = value;
Assert::AreEqual((void*) &expected, (void*) &actual);
}
};

View File

@ -0,0 +1,91 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonPrettyPrint.h"
#include "StringBuilder.h"
using namespace ArduinoJson::Internals;
using namespace ArduinoJson::Generator;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace JsonGeneratorTests
{
TEST_CLASS(PrettyPrint_Array_Tests)
{
char buffer[1024];
size_t returnValue;
public:
TEST_METHOD(EmptyArray)
{
whenInputIs("[]");
outputMustBe("[]");
}
TEST_METHOD(OneElement)
{
whenInputIs("[1]");
outputMustBe(
"[\r\n"
" 1\r\n"
"]");
}
TEST_METHOD(TwoElements)
{
whenInputIs("[1,2]");
outputMustBe(
"[\r\n"
" 1,\r\n"
" 2\r\n"
"]");
}
TEST_METHOD(EmptyNestedArrays)
{
whenInputIs("[[],[]]");
outputMustBe(
"[\r\n"
" [],\r\n"
" []\r\n"
"]");
}
TEST_METHOD(NestedArrays)
{
whenInputIs("[[1,2],[3,4]]");
outputMustBe(
"[\r\n"
" [\r\n"
" 1,\r\n"
" 2\r\n"
" ],\r\n"
" [\r\n"
" 3,\r\n"
" 4\r\n"
" ]\r\n"
"]");
}
private:
void whenInputIs(const char input[])
{
StringBuilder sb(buffer, sizeof(buffer));
IndentedPrint indentedPrint(sb);
JsonPrettyPrint decorator(indentedPrint);
returnValue = decorator.print(input);
}
void outputMustBe(const char* expected)
{
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), returnValue);
}
};
}

View File

@ -0,0 +1,89 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonPrettyPrint.h"
#include "StringBuilder.h"
using namespace ArduinoJson::Internals;
using namespace ArduinoJson::Generator;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace JsonGeneratorTests
{
TEST_CLASS(PrettyPrint_Object_Tests)
{
char buffer[1024];
size_t returnValue;
public:
TEST_METHOD(EmptyObject)
{
whenInputIs("{}");
outputMustBe("{}");
}
TEST_METHOD(OneMember)
{
whenInputIs("{\"key\":\"value\"}");
outputMustBe(
"{\r\n"
" \"key\": \"value\"\r\n"
"}");
}
TEST_METHOD(TwoMembers)
{
whenInputIs("{\"key1\":\"value1\",\"key2\":\"value2\"}");
outputMustBe(
"{\r\n"
" \"key1\": \"value1\",\r\n"
" \"key2\": \"value2\"\r\n"
"}");
}
TEST_METHOD(EmptyNestedObjects)
{
whenInputIs("{\"key1\":{},\"key2\":{}}");
outputMustBe(
"{\r\n"
" \"key1\": {},\r\n"
" \"key2\": {}\r\n"
"}");
}
TEST_METHOD(NestedObjects)
{
whenInputIs("{\"key1\":{\"a\":1},\"key2\":{\"b\":2}}");
outputMustBe(
"{\r\n"
" \"key1\": {\r\n"
" \"a\": 1\r\n"
" },\r\n"
" \"key2\": {\r\n"
" \"b\": 2\r\n"
" }\r\n"
"}");
}
private:
void whenInputIs(const char input[])
{
StringBuilder sb(buffer, sizeof(buffer));
IndentedPrint indentedPrint(sb);
JsonPrettyPrint decorator(indentedPrint);
returnValue = decorator.print(input);
}
void outputMustBe(const char* expected)
{
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), returnValue);
}
};
}

View File

@ -0,0 +1,76 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonPrettyPrint.h"
#include "StringBuilder.h"
using namespace ArduinoJson::Internals;
using namespace ArduinoJson::Generator;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace JsonGeneratorTests
{
TEST_CLASS(PrettyPrint_String_Tests)
{
char buffer[1024];
size_t returnValue;
public:
TEST_METHOD(EmptyString)
{
whenInputIs("");
outputMustBe("");
}
TEST_METHOD(TrickyCharacters)
{
whenInputIs ("\":\\\"',\"");
outputMustBe("\":\\\"',\"");
}
TEST_METHOD(OpeningCurlyBrace)
{
whenInputIs ("\"{\"");
outputMustBe("\"{\"");
}
TEST_METHOD(OpeningSquareBrace)
{
whenInputIs("\"[\"");
outputMustBe("\"[\"");
}
TEST_METHOD(ClosingCurlyBrace)
{
whenInputIs("\"}\"");
outputMustBe("\"}\"");
}
TEST_METHOD(ClosingSquareBrace)
{
whenInputIs("\"]\"");
outputMustBe("\"]\"");
}
private:
void whenInputIs(const char input[])
{
StringBuilder sb(buffer, sizeof(buffer));
IndentedPrint indentedPrint(sb);
JsonPrettyPrint decorator(indentedPrint);
returnValue = decorator.print(input);
}
void outputMustBe(const char* expected)
{
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), returnValue);
}
};
}

View File

@ -0,0 +1,43 @@
/*
* Arduino JSON library - IndentedPrint example
* Benoit Blanchon 2014 - MIT License
*/
#include <JsonGenerator.h>
using namespace ArduinoJson::Generator;
void setup()
{
Serial.begin(9600);
JsonObject<1> json;
json["key"] = "value";
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.println("You can print JSON here, as usual:");
serial.println(json);
serial.println();
serial.println("But you can also prettyPrint JSON here:");
json.prettyPrintTo(serial);
serial.println();
serial.unindent();
serial.unindent();
serial.println("This is back at indentation 0");
}
void loop()
{
}

View File

@ -21,6 +21,9 @@ void setup()
root["data"] = array;
Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
Serial.println();
root.prettyPrintTo(Serial); // same string indented
}
void loop()