forked from bblanchon/ArduinoJson
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
7246db7691 | |||
4bdbc6c1fc | |||
8e6fdb20eb | |||
016d0d699e | |||
6771603a05 | |||
d067cf0e84 | |||
13593d73a3 | |||
bc86ae800a | |||
df52dceaa1 |
13
BuildArduinoPackage.sh
Normal file
13
BuildArduinoPackage.sh
Normal 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
|
@ -1,6 +1,11 @@
|
|||||||
Arduino JSON: change log
|
Arduino JSON: change log
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
v3.2
|
||||||
|
----
|
||||||
|
|
||||||
|
* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1).
|
||||||
|
|
||||||
v3.1
|
v3.1
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -20,12 +20,34 @@ namespace ArduinoJson
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
void add(const Printable& value)
|
||||||
void add(T 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>
|
template<int DIGITS>
|
||||||
@ -44,6 +66,13 @@ namespace ArduinoJson
|
|||||||
private:
|
private:
|
||||||
JsonValue* items;
|
JsonValue* items;
|
||||||
int capacity, count;
|
int capacity, count;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void addIfPossible(T value)
|
||||||
|
{
|
||||||
|
if (count < capacity)
|
||||||
|
items[count++] = value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -35,7 +35,7 @@ namespace ArduinoJson
|
|||||||
content.asLong = value;
|
content.asLong = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator=(Printable& value)
|
void operator=(const Printable& value)
|
||||||
{
|
{
|
||||||
printToImpl = &printPrintableTo;
|
printToImpl = &printPrintableTo;
|
||||||
content.asPrintable = &value;
|
content.asPrintable = &value;
|
||||||
@ -89,7 +89,7 @@ namespace ArduinoJson
|
|||||||
return content.asLong;
|
return content.asLong;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator Printable&()
|
operator const Printable&()
|
||||||
{
|
{
|
||||||
return *content.asPrintable;
|
return *content.asPrintable;
|
||||||
}
|
}
|
||||||
@ -109,11 +109,11 @@ namespace ArduinoJson
|
|||||||
private:
|
private:
|
||||||
union Content
|
union Content
|
||||||
{
|
{
|
||||||
bool asBool;
|
bool asBool;
|
||||||
double asDouble;
|
double asDouble;
|
||||||
long asLong;
|
long asLong;
|
||||||
Printable* asPrintable;
|
const Printable* asPrintable;
|
||||||
const char* asString;
|
const char* asString;
|
||||||
};
|
};
|
||||||
|
|
||||||
Content content;
|
Content content;
|
||||||
|
@ -101,6 +101,33 @@ or
|
|||||||
JsonObject<8> nestedObject;
|
JsonObject<8> nestedObject;
|
||||||
array.add(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
|
#### JSON Object
|
||||||
|
|
||||||
You create a JSON object (ie hash-table/dictionary) with the following line:
|
You create a JSON object (ie hash-table/dictionary) with the following line:
|
||||||
|
73
JsonGeneratorTests/Issue10.cpp
Normal file
73
JsonGeneratorTests/Issue10.cpp
Normal 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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -14,7 +14,7 @@ namespace JsonGeneratorTests
|
|||||||
{
|
{
|
||||||
TEST_CLASS(JsonArrayTests)
|
TEST_CLASS(JsonArrayTests)
|
||||||
{
|
{
|
||||||
JsonArray<2> arr;
|
JsonArray<2> array;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -26,111 +26,117 @@ namespace JsonGeneratorTests
|
|||||||
|
|
||||||
TEST_METHOD(Null)
|
TEST_METHOD(Null)
|
||||||
{
|
{
|
||||||
add((char*)0);
|
array.add((char*) 0);
|
||||||
|
|
||||||
outputMustBe("[null]");
|
outputMustBe("[null]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneString)
|
TEST_METHOD(OneString)
|
||||||
{
|
{
|
||||||
add("hello");
|
array.add("hello");
|
||||||
|
|
||||||
outputMustBe("[\"hello\"]");
|
outputMustBe("[\"hello\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(TwoStrings)
|
TEST_METHOD(TwoStrings)
|
||||||
{
|
{
|
||||||
add("hello");
|
array.add("hello");
|
||||||
add("world");
|
array.add("world");
|
||||||
|
|
||||||
outputMustBe("[\"hello\",\"world\"]");
|
outputMustBe("[\"hello\",\"world\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneStringOverCapacity)
|
TEST_METHOD(OneStringOverCapacity)
|
||||||
{
|
{
|
||||||
add("hello");
|
array.add("hello");
|
||||||
add("world");
|
array.add("world");
|
||||||
add("lost");
|
array.add("lost");
|
||||||
|
|
||||||
outputMustBe("[\"hello\",\"world\"]");
|
outputMustBe("[\"hello\",\"world\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneDoubleDefaultDigits)
|
TEST_METHOD(OneDoubleDefaultDigits)
|
||||||
{
|
{
|
||||||
add(3.14159265358979323846);
|
array.add(3.14159265358979323846);
|
||||||
outputMustBe("[3.14]");
|
outputMustBe("[3.14]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneDoubleFourDigits)
|
TEST_METHOD(OneDoubleFourDigits)
|
||||||
{
|
{
|
||||||
add<4>(3.14159265358979323846);
|
array.add<4>(3.14159265358979323846);
|
||||||
outputMustBe("[3.1416]");
|
outputMustBe("[3.1416]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneInteger)
|
TEST_METHOD(OneInteger)
|
||||||
{
|
{
|
||||||
add(1);
|
array.add(1);
|
||||||
|
|
||||||
outputMustBe("[1]");
|
outputMustBe("[1]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(TwoIntegers)
|
TEST_METHOD(TwoIntegers)
|
||||||
{
|
{
|
||||||
add(1);
|
array.add(1);
|
||||||
add(2);
|
array.add(2);
|
||||||
|
|
||||||
outputMustBe("[1,2]");
|
outputMustBe("[1,2]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneIntegerOverCapacity)
|
TEST_METHOD(OneIntegerOverCapacity)
|
||||||
{
|
{
|
||||||
add(1);
|
array.add(1);
|
||||||
add(2);
|
array.add(2);
|
||||||
add(3);
|
array.add(3);
|
||||||
|
|
||||||
outputMustBe("[1,2]");
|
outputMustBe("[1,2]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneTrue)
|
TEST_METHOD(OneTrue)
|
||||||
{
|
{
|
||||||
add(true);
|
array.add(true);
|
||||||
|
|
||||||
outputMustBe("[true]");
|
outputMustBe("[true]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneFalse)
|
TEST_METHOD(OneFalse)
|
||||||
{
|
{
|
||||||
add(false);
|
array.add(false);
|
||||||
|
|
||||||
outputMustBe("[false]");
|
outputMustBe("[false]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(TwoBooleans)
|
TEST_METHOD(TwoBooleans)
|
||||||
{
|
{
|
||||||
add(false);
|
array.add(false);
|
||||||
add(true);
|
array.add(true);
|
||||||
|
|
||||||
outputMustBe("[false,true]");
|
outputMustBe("[false,true]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneBooleanOverCapacity)
|
TEST_METHOD(OneBooleanOverCapacity)
|
||||||
{
|
{
|
||||||
add(false);
|
array.add(false);
|
||||||
add(true);
|
array.add(true);
|
||||||
add(false);
|
array.add(false);
|
||||||
|
|
||||||
outputMustBe("[false,true]");
|
outputMustBe("[false,true]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneEmptyNestedArray)
|
TEST_METHOD(OneEmptyNestedArray)
|
||||||
{
|
{
|
||||||
addNested(JsonArray<1>());
|
JsonArray<1> nestedArray;
|
||||||
|
|
||||||
|
array.add(nestedArray);
|
||||||
|
|
||||||
outputMustBe("[[]]");
|
outputMustBe("[[]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_METHOD(OneEmptyNestedHash)
|
TEST_METHOD(OneEmptyNestedHash)
|
||||||
{
|
{
|
||||||
addNested(JsonHashTable<1>());
|
JsonObject<1> nestedObject;
|
||||||
|
|
||||||
|
array.add(nestedObject);
|
||||||
|
|
||||||
outputMustBe("[{}]");
|
outputMustBe("[{}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,33 +145,16 @@ namespace JsonGeneratorTests
|
|||||||
JsonArray<1> nestedArray;
|
JsonArray<1> nestedArray;
|
||||||
nestedArray.add(1);
|
nestedArray.add(1);
|
||||||
|
|
||||||
addNested(nestedArray);
|
array.add(nestedArray);
|
||||||
|
|
||||||
outputMustBe("[[1]]");
|
outputMustBe("[[1]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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)
|
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(expected, buffer);
|
||||||
Assert::AreEqual(strlen(expected), n);
|
Assert::AreEqual(strlen(expected), n);
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,7 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="EscapedStringTests.cpp" />
|
<ClCompile Include="EscapedStringTests.cpp" />
|
||||||
|
<ClCompile Include="Issue10.cpp" />
|
||||||
<ClCompile Include="JsonArrayTests.cpp" />
|
<ClCompile Include="JsonArrayTests.cpp" />
|
||||||
<ClCompile Include="JsonObject_Indexer_Tests.cpp" />
|
<ClCompile Include="JsonObject_Indexer_Tests.cpp" />
|
||||||
<ClCompile Include="JsonObject_PrintTo_Tests.cpp" />
|
<ClCompile Include="JsonObject_PrintTo_Tests.cpp" />
|
||||||
|
@ -36,5 +36,8 @@
|
|||||||
<ClCompile Include="JsonValue_Cast_Tests.cpp">
|
<ClCompile Include="JsonValue_Cast_Tests.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Issue10.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -71,7 +71,7 @@ namespace JsonGeneratorTests
|
|||||||
void setValueAndCheckCast(JsonArray<N>& expected)
|
void setValueAndCheckCast(JsonArray<N>& expected)
|
||||||
{
|
{
|
||||||
value = expected;
|
value = expected;
|
||||||
Printable& actual = value;
|
const Printable& actual = value;
|
||||||
Assert::AreEqual((void*) &expected, (void*) &actual);
|
Assert::AreEqual((void*) &expected, (void*) &actual);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user