mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-16 20:12:16 +02:00
Added JSON_PROXY to copy arrays and objects by reference
This commit is contained in:
@ -3,11 +3,16 @@
|
|||||||
#include "JsonWriter.h"
|
#include "JsonWriter.h"
|
||||||
#include "../JsonArray.h"
|
#include "../JsonArray.h"
|
||||||
#include "../JsonObject.h"
|
#include "../JsonObject.h"
|
||||||
|
#include "../JsonBuffer.h"
|
||||||
|
|
||||||
void JsonNode::writeTo(JsonWriter& writer)
|
void JsonNode::writeTo(JsonWriter& writer)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case JSON_PROXY:
|
||||||
|
content.asProxy.target->writeTo(writer);
|
||||||
|
break;
|
||||||
|
|
||||||
case JSON_ARRAY:
|
case JSON_ARRAY:
|
||||||
writeArrayTo(writer);
|
writeArrayTo(writer);
|
||||||
break;
|
break;
|
||||||
@ -36,7 +41,11 @@ void JsonNode::writeTo(JsonWriter& writer)
|
|||||||
|
|
||||||
void JsonNode::addChild(JsonNode* childToAdd)
|
void JsonNode::addChild(JsonNode* childToAdd)
|
||||||
{
|
{
|
||||||
if (type != JSON_ARRAY && type != JSON_OBJECT) return;
|
if (type == JSON_PROXY)
|
||||||
|
return content.asProxy.target->addChild(childToAdd);
|
||||||
|
|
||||||
|
if (type != JSON_ARRAY && type != JSON_OBJECT)
|
||||||
|
return;
|
||||||
|
|
||||||
JsonNode* lastChild = content.asContainer.child;
|
JsonNode* lastChild = content.asContainer.child;
|
||||||
|
|
||||||
@ -54,6 +63,9 @@ void JsonNode::addChild(JsonNode* childToAdd)
|
|||||||
|
|
||||||
void JsonNode::removeChild(JsonNode* childToRemove)
|
void JsonNode::removeChild(JsonNode* childToRemove)
|
||||||
{
|
{
|
||||||
|
if (type == JSON_PROXY)
|
||||||
|
return content.asProxy.target->removeChild(childToRemove);
|
||||||
|
|
||||||
if (type != JSON_ARRAY && type != JSON_OBJECT) return;
|
if (type != JSON_ARRAY && type != JSON_OBJECT) return;
|
||||||
|
|
||||||
if (content.asContainer.child == childToRemove)
|
if (content.asContainer.child == childToRemove)
|
||||||
@ -122,3 +134,16 @@ void JsonNode::writeObjectTo(JsonWriter& writer)
|
|||||||
writer.writeEmptyObject();
|
writer.writeEmptyObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JsonNode::setAsProxyOfSelf()
|
||||||
|
{
|
||||||
|
JsonBuffer* buffer = content.asContainer.buffer;
|
||||||
|
if (!buffer) return;
|
||||||
|
|
||||||
|
JsonNode* newNode = buffer->createNode();
|
||||||
|
if (!newNode) return;
|
||||||
|
|
||||||
|
*newNode = *this;
|
||||||
|
|
||||||
|
setAsProxyOf(newNode);
|
||||||
|
}
|
@ -18,6 +18,7 @@ class JsonNode
|
|||||||
JSON_BOOLEAN,
|
JSON_BOOLEAN,
|
||||||
JSON_STRING,
|
JSON_STRING,
|
||||||
JSON_LONG,
|
JSON_LONG,
|
||||||
|
JSON_PROXY,
|
||||||
JSON_DOUBLE_0_DECIMALS,
|
JSON_DOUBLE_0_DECIMALS,
|
||||||
JSON_DOUBLE_1_DECIMAL,
|
JSON_DOUBLE_1_DECIMAL,
|
||||||
JSON_DOUBLE_2_DECIMALS,
|
JSON_DOUBLE_2_DECIMALS,
|
||||||
@ -126,11 +127,13 @@ public:
|
|||||||
|
|
||||||
JsonBuffer* getContainerBuffer()
|
JsonBuffer* getContainerBuffer()
|
||||||
{
|
{
|
||||||
|
if (type == JSON_PROXY) return content.asProxy.target->getContainerBuffer();
|
||||||
return type == JSON_ARRAY || type == JSON_OBJECT ? content.asContainer.buffer : 0;
|
return type == JSON_ARRAY || type == JSON_OBJECT ? content.asContainer.buffer : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode* getContainerChild()
|
JsonNode* getContainerChild()
|
||||||
{
|
{
|
||||||
|
if (type == JSON_PROXY) return content.asProxy.target->getContainerChild();
|
||||||
return type == JSON_ARRAY || type == JSON_OBJECT ? content.asContainer.child : 0;
|
return type == JSON_ARRAY || type == JSON_OBJECT ? content.asContainer.child : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +151,23 @@ public:
|
|||||||
|
|
||||||
void removeChild(JsonNode* childToRemove);
|
void removeChild(JsonNode* childToRemove);
|
||||||
|
|
||||||
|
void duplicate(JsonNode* other)
|
||||||
|
{
|
||||||
|
if (!other)
|
||||||
|
{
|
||||||
|
type = JSON_UNDEFINED;
|
||||||
|
}
|
||||||
|
else if (other->type == JSON_ARRAY || other->type==JSON_OBJECT)
|
||||||
|
{
|
||||||
|
other->setAsProxyOfSelf();
|
||||||
|
setAsProxyOf(other->content.asProxy.target);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*this = *other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonNode* next;
|
JsonNode* next;
|
||||||
JsonNodeContent content;
|
JsonNodeContent content;
|
||||||
@ -155,4 +175,12 @@ private:
|
|||||||
|
|
||||||
inline void writeArrayTo(JsonWriter&);// TODO: <- move in JsonNodeSerializer
|
inline void writeArrayTo(JsonWriter&);// TODO: <- move in JsonNodeSerializer
|
||||||
inline void writeObjectTo(JsonWriter&);// TODO: <- move in JsonNodeSerializer
|
inline void writeObjectTo(JsonWriter&);// TODO: <- move in JsonNodeSerializer
|
||||||
|
|
||||||
|
void setAsProxyOfSelf();
|
||||||
|
|
||||||
|
void setAsProxyOf(JsonNode* target)
|
||||||
|
{
|
||||||
|
type = JSON_PROXY;
|
||||||
|
content.asProxy.target = target;
|
||||||
|
}
|
||||||
};
|
};
|
37
srcs/Internals/JsonNodeWrapper.h
Normal file
37
srcs/Internals/JsonNodeWrapper.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JsonNode.h"
|
||||||
|
class JsonValue;
|
||||||
|
|
||||||
|
class JsonNodeWrapper
|
||||||
|
{
|
||||||
|
friend JsonValue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
JsonNodeWrapper()
|
||||||
|
: _node(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit JsonNodeWrapper(JsonNode* node)
|
||||||
|
: _node(node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void duplicate(const JsonNodeWrapper& other)
|
||||||
|
{
|
||||||
|
if (!_node)
|
||||||
|
{
|
||||||
|
_node = other._node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_node->duplicate(other._node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonNode* _node;
|
||||||
|
};
|
||||||
|
|
@ -50,6 +50,7 @@ void JsonArray::add(long value)
|
|||||||
addChild(node);
|
addChild(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: we should have the same issue as in JsonValue
|
||||||
void JsonArray::add(JsonContainer nestedContainer)
|
void JsonArray::add(JsonContainer nestedContainer)
|
||||||
{
|
{
|
||||||
JsonNode* node = createNode();
|
JsonNode* node = createNode();
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
class JsonBuffer
|
class JsonBuffer
|
||||||
{
|
{
|
||||||
friend class JsonContainer;
|
friend class JsonContainer;
|
||||||
|
friend class JsonNode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~JsonBuffer() {};
|
virtual ~JsonBuffer() {};
|
||||||
|
@ -4,24 +4,23 @@
|
|||||||
#include "Internals/JsonNodeIterator.h"
|
#include "Internals/JsonNodeIterator.h"
|
||||||
#include "Internals/JsonNode.h"
|
#include "Internals/JsonNode.h"
|
||||||
#include "Internals/IndentedPrint.h"
|
#include "Internals/IndentedPrint.h"
|
||||||
|
#include "Internals/JsonNodeWrapper.h"
|
||||||
class JsonArray;
|
class JsonArray;
|
||||||
class JsonObject;
|
class JsonObject;
|
||||||
class JsonValue;
|
class JsonValue;
|
||||||
|
|
||||||
class JsonContainer : public Printable
|
class JsonContainer : public Printable, public JsonNodeWrapper
|
||||||
{
|
{
|
||||||
friend JsonValue;
|
// friend JsonValue;
|
||||||
friend JsonArray;
|
friend JsonArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonContainer()
|
|
||||||
: _node(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonContainer(JsonNode* node)
|
|
||||||
: _node(node)
|
JsonContainer() {}
|
||||||
|
|
||||||
|
explicit JsonContainer(JsonNode* node)
|
||||||
|
: JsonNodeWrapper(node)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +53,5 @@ protected:
|
|||||||
void addChild(JsonNode*);
|
void addChild(JsonNode*);
|
||||||
void removeChild(JsonNode*);
|
void removeChild(JsonNode*);
|
||||||
JsonNode* createNode();
|
JsonNode* createNode();
|
||||||
|
|
||||||
JsonNode* _node;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,32 +28,6 @@ void JsonValue::operator=(int value)
|
|||||||
_node->setAsLong(value);
|
_node->setAsLong(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: it's a duplicate
|
|
||||||
void JsonValue::operator=(const JsonContainer& object)
|
|
||||||
{
|
|
||||||
if (!_node)
|
|
||||||
{
|
|
||||||
_node = object._node;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*_node = *object._node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: it's a duplicate
|
|
||||||
void JsonValue::operator=(JsonValue const& value)
|
|
||||||
{
|
|
||||||
if (!_node)
|
|
||||||
{
|
|
||||||
_node = value._node;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*_node = *value._node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonValue::operator bool() const
|
JsonValue::operator bool() const
|
||||||
{
|
{
|
||||||
return _node ? _node->getAsBoolean() : false;
|
return _node ? _node->getAsBoolean() : false;
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Internals/JsonNodeWrapper.h"
|
||||||
|
|
||||||
class JsonArray;
|
class JsonArray;
|
||||||
class JsonContainer;
|
class JsonContainer;
|
||||||
class JsonObject;
|
class JsonObject;
|
||||||
class JsonNode;
|
|
||||||
|
|
||||||
class JsonValue
|
class JsonValue : public JsonNodeWrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit JsonValue()
|
JsonValue() {}
|
||||||
: _node(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit JsonValue(JsonNode* node)
|
explicit JsonValue(JsonNode* node)
|
||||||
: _node(node)
|
: JsonNodeWrapper(node)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,8 +21,8 @@ public:
|
|||||||
void operator=(const char*);
|
void operator=(const char*);
|
||||||
void operator=(double x) { set(x, 2); }
|
void operator=(double x) { set(x, 2); }
|
||||||
void operator=(int);
|
void operator=(int);
|
||||||
void operator=(const JsonContainer&);
|
void operator=(const JsonValue& value) { duplicate(value); }
|
||||||
void operator=(const JsonValue&);
|
void operator=(const JsonNodeWrapper& object) { duplicate(object); }
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
operator const char*() const;
|
operator const char*() const;
|
||||||
@ -35,7 +33,4 @@ public:
|
|||||||
operator JsonObject() const;
|
operator JsonObject() const;
|
||||||
|
|
||||||
void set(double value, int decimals);
|
void set(double value, int decimals);
|
||||||
|
|
||||||
private:
|
|
||||||
JsonNode* _node;
|
|
||||||
};
|
};
|
@ -83,6 +83,7 @@
|
|||||||
<ClInclude Include="Internals\JsonWriter.h" />
|
<ClInclude Include="Internals\JsonWriter.h" />
|
||||||
<ClInclude Include="JsonContainer.h" />
|
<ClInclude Include="JsonContainer.h" />
|
||||||
<ClInclude Include="Internals\JsonNodeIterator.h" />
|
<ClInclude Include="Internals\JsonNodeIterator.h" />
|
||||||
|
<ClInclude Include="Internals\JsonNodeWrapper.h" />
|
||||||
<ClInclude Include="JsonObject.h" />
|
<ClInclude Include="JsonObject.h" />
|
||||||
<ClInclude Include="JsonValue.h" />
|
<ClInclude Include="JsonValue.h" />
|
||||||
<ClInclude Include="Arduino\Print.h" />
|
<ClInclude Include="Arduino\Print.h" />
|
||||||
|
@ -63,6 +63,9 @@
|
|||||||
<ClInclude Include="Internals\IndentedPrint.h">
|
<ClInclude Include="Internals\IndentedPrint.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Internals\JsonNodeWrapper.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="JsonObject.cpp">
|
<ClCompile Include="JsonObject.cpp">
|
||||||
|
@ -123,21 +123,35 @@ TEST_F(JsonObject_Serialization_Tests, OneFalse)
|
|||||||
object["key"] = false;
|
object["key"] = false;
|
||||||
outputMustBe("{\"key\":false}");
|
outputMustBe("{\"key\":false}");
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedArray)
|
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedArrayViaProxy)
|
||||||
{
|
{
|
||||||
auto nestedArray = JsonArray<1>();
|
auto nestedArray = json.createArray();
|
||||||
|
|
||||||
object["key"] = nestedArray;
|
object["key"] = nestedArray;
|
||||||
|
|
||||||
outputMustBe("{\"key\":[]}");
|
outputMustBe("{\"key\":[]}");
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedObject)
|
|
||||||
{
|
|
||||||
auto nestedObject = json.createObject();
|
|
||||||
|
|
||||||
object["key"] = nestedObject;
|
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedObjectViaProxy)
|
||||||
|
{
|
||||||
|
auto nestedArray = json.createObject();
|
||||||
|
|
||||||
|
object["key"] = nestedArray;
|
||||||
|
|
||||||
outputMustBe("{\"key\":{}}");
|
outputMustBe("{\"key\":{}}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedObject)
|
||||||
|
{
|
||||||
|
object.createNestedObject("key");
|
||||||
|
|
||||||
|
outputMustBe("{\"key\":{}}");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedArray)
|
||||||
|
{
|
||||||
|
object.createNestedArray("key");
|
||||||
|
|
||||||
|
outputMustBe("{\"key\":[]}");
|
||||||
|
}
|
@ -101,12 +101,10 @@ TEST_F(JsonValueTests, ObjectsAreCopiedByReference)
|
|||||||
JsonObject object = json.createObject();
|
JsonObject object = json.createObject();
|
||||||
|
|
||||||
jsonValue1 = object;
|
jsonValue1 = object;
|
||||||
jsonValue2 = jsonValue1;
|
|
||||||
|
|
||||||
object["hello"] = "world";
|
object["hello"] = "world";
|
||||||
jsonValue1 = 0;
|
|
||||||
|
|
||||||
EXPECT_EQ(1, ((JsonObject) jsonValue2).size());
|
EXPECT_EQ(1, ((JsonObject) jsonValue1).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(JsonValueTests, ArraysAreCopiedByReference)
|
TEST_F(JsonValueTests, ArraysAreCopiedByReference)
|
||||||
@ -114,10 +112,8 @@ TEST_F(JsonValueTests, ArraysAreCopiedByReference)
|
|||||||
JsonArray array = json.createArray();
|
JsonArray array = json.createArray();
|
||||||
|
|
||||||
jsonValue1 = array;
|
jsonValue1 = array;
|
||||||
jsonValue2 = jsonValue1;
|
|
||||||
jsonValue1 = 0;
|
|
||||||
|
|
||||||
array.add("world");
|
array.add("world");
|
||||||
|
|
||||||
EXPECT_EQ(1, ((JsonObject) jsonValue2).size());
|
EXPECT_EQ(1, ((JsonObject) jsonValue1).size());
|
||||||
}
|
}
|
Reference in New Issue
Block a user