8000 Create or assign a JsonDocument from a JsonArray/JsonObject/JsonVariant · tschaban/ArduinoJson@4167b11 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4167b11

Browse files
committed
Create or assign a JsonDocument from a JsonArray/JsonObject/JsonVariant
1 parent 2a3b51a commit 4167b11

File tree

10 files changed

+331
-95
lines changed

10 files changed

+331
-95
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ HEAD
1515
* Replaced `JsonDocument::nestingLimit` with an additional parameter
1616
to `deserializeJson()` and `deserializeMsgPack()`
1717
* Fixed uninitialized variant in `JsonDocument`
18+
* Fixed `StaticJsonDocument` copy constructor and copy assignment
19+
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
20+
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
1821
* Added `JsonDocument::isNull()`
1922

2023
> ### BREAKING CHANGES

src/ArduinoJson/Document/DynamicJsonDocument.hpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,24 @@ namespace ARDUINOJSON_NAMESPACE {
1313
class DynamicJsonDocument : public JsonDocument {
1414
public:
1515
explicit DynamicJsonDocument(size_t capa)
16-
: JsonDocument(allocPool(addPadding(capa))) {}
16+
: JsonDocument(allocPool(capa)) {}
1717

1818
DynamicJsonDocument(const DynamicJsonDocument& src)
19-
: JsonDocument(allocPool(src.capacity())) {
20-
copy(src);
19+
: JsonDocument(allocPool(src.memoryUsage())) {
20+
set(src);
2121
}
2222

23-
DynamicJsonDocument(const JsonDocument& src)
24-
: JsonDocument(allocPool(src.capacity())) {
25-
copy(src);
23+
template <typename T>
24+
DynamicJsonDocument(const T& src,
25+
typename enable_if<IsVisitable<T>::value>::type* = 0)
26+
: JsonDocument(allocPool(src.memoryUsage())) {
27+
set(src);
28+
}
29+
30+
// disambiguate
31+
DynamicJsonDocument(VariantRef src)
32+
: JsonDocument(allocPool(src.memoryUsage())) {
33+
set(src);
2634
}
2735

2836
~DynamicJsonDocument() {
@@ -31,19 +39,20 @@ class DynamicJsonDocument : public JsonDocument {
3139

3240
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
3341
reallocPoolIfTooSmall(src.memoryUsage());
34-
copy(src);
42+
set(src);
3543
return *this;
3644
}
3745

3846
template <typename T>
39-
DynamicJsonDocument& operator=(const JsonDocument& src) {
47+
DynamicJsonDocument& operator=(const T& src) {
4048
reallocPoolIfTooSmall(src.memoryUsage());
41-
copy(src);
49+
set(src);
4250
return *this;
4351
}
4452

4553
private:
46-
MemoryPool allocPool(size_t capa) {
54+
MemoryPool allocPool(size_t requiredSize) {
55+
size_t capa = addPadding(requiredSize);
4756
return MemoryPool(reinterpret_cast<char*>(malloc(capa)), capa);
4857
}
4958

src/ArduinoJson/Document/JsonDocument.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#pragma once
66

77
#include "../Memory/MemoryPool.hpp"
8+
#include "../Object/ObjectRef.hpp"
89
#include "../Variant/VariantRef.hpp"
910
#include "../Variant/VariantTo.hpp"
1011

@@ -53,6 +54,16 @@ class JsonDocument : public Visitable {
5354
return _pool.capacity();
5455
}
5556

57+
bool set(const JsonDocument& src) {
58+
return to<VariantRef>().set(src.as<VariantRef>());
59+
}
60+
61+
template <typename T>
62+
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
63+
const T& src) {
64+
return to<VariantRef>().set(src);
65+
}
66+
5667
template <typename T>
5768
typename VariantTo<T>::type to() {
5869
clear();

src/ArduinoJson/Document/StaticJsonDocument.hpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,31 @@ class StaticJsonDocument : public JsonDocument {
1616
public:
1717
StaticJsonDocument() : JsonDocument(_buffer, ACTUAL_CAPACITY) {}
1818

19-
StaticJsonDocument(const JsonDocument& src)
19+
StaticJsonDocument(const StaticJsonDocument& src)
2020
: JsonDocument(_buffer, ACTUAL_CAPACITY) {
21-
copy(src);
21+
set(src);
2222
}
2323

24-
StaticJsonDocument operator=(const JsonDocument& src) {
25-
copy(src);
24+
template <typename T>
25+
StaticJsonDocument(const T& src,
26+
typename enable_if<IsVisitable<T>::value>::type* = 0)
27+
: JsonDocument(_buffer, ACTUAL_CAPACITY) {
28+
set(src);
29+
}
30+
31+
// disambiguate
32+
StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, ACTUAL_CAPACITY) {
33+
set(src);
34+
}
35+
36+
StaticJsonDocument operator=(const StaticJsonDocument& src) {
37+
set(src);
38+
return *this;
39+
}
40+
41+
template <typename T>
42+
StaticJsonDocument operator=(const T& src) {
43+
set(src);
2644
return *this;
2745
}
2846

src/ArduinoJson/Variant/VariantAs.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ variantAs(const VariantData* _data) {
7777
return _data != 0 ? _data->asString() : 0;
7878
}
7979

80+
template <typename T>
81+
inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
82+
const VariantData* _data);
83+
84+
template <typename T>
85+
inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
86+
const VariantData* _data);
87+
8088
template <typename T>
8189
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
8290
variantAs(const VariantData* _data);

src/ArduinoJson/Variant/VariantAsImpl.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,23 @@
55
#pragma once
66

77
#include "../Serialization/DynamicStringWriter.hpp"
8+
#include "VariantFunctions.hpp"
89
#include "VariantRef.hpp"
910

1011
namespace ARDUINOJSON_NAMESPACE {
1112

13+
template <typename T>
14+
inline typename enable_if<is_same<ArrayConstRef, T>::value, T>::type variantAs(
15+
const VariantData* _data) {
16+
return ArrayConstRef(variantAsArray(_data));
17+
}
18+
19+
template <typename T>
20+
inline typename enable_if<is_same<ObjectConstRef, T>::value, T>::type variantAs(
21+
const VariantData* _data) {
22+
return ObjectConstRef(variantAsObject(_data));
23+
}
24+
1225
template <typename T>
1326
inline typename enable_if<is_same<VariantConstRef, T>::value, T>::type
1427
variantAs(const VariantData* _data) {

src/ArduinoJson/Variant/VariantData.hpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,15 @@ class VariantData {
6767
}
6868

6969
CollectionData *asArray() {
70-
if (type() == VALUE_IS_ARRAY)
71-
return &_content.asCollection;
72-
else
73-
return 0;
70+
return type() == VALUE_IS_ARRAY ? &_content.asCollection : 0;
7471
}
7572

7673
const CollectionData *asArray() const {
7774
return const_cast<VariantData *>(this)->asArray();
7875
}
7976

8077
CollectionData *asObject() {
81-
if (type() == VALUE_IS_OBJECT)
82-
return &_content.asCollection;
83-
else
84-
return 0;
78+
return type() == VALUE_IS_OBJECT ? &_content.asCollection : 0;
8579
}
8680

8781
const CollectionData *asObject() const {

src/ArduinoJson/Variant/VariantFunctions.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ inline void variantAccept(const VariantData *var, Visitor &visitor) {
1616
visitor.visitNull();
1717
}
1818

19+
inline const CollectionData *variantAsArray(const VariantData *var) {
20+
return var != 0 ? var->asArray() : 0;
21+
}
22+
1923
inline const CollectionData *variantAsObject(const VariantData *var) {
2024
return var != 0 ? var->asObject() : 0;
2125
}

test/JsonDocument/DynamicJsonDocument.cpp

Lines changed: 94 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
#include <ArduinoJson.h>
66
#include <catch.hpp>
77

8+
using ARDUINOJSON_NAMESPACE::addPadding;
9+
10+
static void REQUIRE_JSON(JsonDocument& doc, const std::string& expected) {
11+
std::string json;
12+
serializeJson(doc, json);
13+
REQUIRE(json == expected);
14+
}
15+
816
TEST_CASE("DynamicJsonDocument") {
917
DynamicJsonDocument doc(4096);
1018

@@ -74,30 +82,70 @@ TEST_CASE("DynamicJsonDocument") {
7482
}
7583
}
7684

77-
TEST_CASE("DynamicJsonDocument copies") {
85+
TEST_CASE("DynamicJsonDocument constructor") {
7886
SECTION("Copy constructor") {
7987
DynamicJsonDocument doc1(1234);
8088
deserializeJson(doc1, "{\"hello\":\"world\"}");
8189

8290
DynamicJsonDocument doc2 = doc1;
8391

84-
std::string json;
85-
serializeJson(doc2, json);
86-
REQUIRE(json == "{\"hello\":\"world\"}");
92+
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
8793

88-
REQUIRE(doc2.capacity() == doc1.capacity());
94+
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
95+
}
96+
97+
SECTION("Construct from StaticJsonDocument") {
98+
StaticJsonDocument<200> doc1;
99+
deserializeJson(doc1, "{\"hello\":\"world\"}");
100+
101+
DynamicJsonDocument doc2 = doc1;
102+
103+
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
104+
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
105+
}
106+
107+
SECTION("Construct from JsonObject") {
108+
StaticJsonDocument<200> doc1;
109+
JsonObject obj = doc1.to<JsonObject>();
110+
obj["hello"] = "world";
111+
112+
DynamicJsonDocument doc2 = obj;
113+
114+
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
115+
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
116+
}
117+
118+
SECTION("Construct from JsonArray") {
119+
StaticJsonDocument<200> doc1;
120+
JsonArray arr = doc1.to<JsonArray>();
121+
arr.add("hello");
122+
123+
DynamicJsonDocument doc2 = arr;
124+
125+
REQUIRE_JSON(doc2, "[\"hello\"]");
126+
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
127+
}
128+
129+
SECTION("Construct from JsonVariant") {
130+
StaticJsonDocument<200> doc1;
131+
deserializeJson(doc1, "42");
132+
133+
DynamicJsonDocument doc2 = doc1.as<JsonVariant>();
134+
135+
REQUIRE_JSON(doc2, "42");
136+
REQUIRE(doc2.capacity() == addPadding(doc1.memoryUsage()));
89137
}
138+
}
90139

140+
TEST_CASE("DynamicJsonDocument assignment") {
91141
SECTION("Copy assignment preserves the buffer when capacity is sufficient") {
92142
DynamicJsonDocument doc1(1234);
93143
deserializeJson(doc1, "{\"hello\":\"world\"}");
94144

95145
DynamicJsonDocument doc2(doc1.capacity());
96146
doc2 = doc1;
97147

98-
std::string json;
99-
serializeJson(doc2, json);
100-
REQUIRE(json == "{\"hello\":\"world\"}");
148+
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
101149
REQUIRE(doc2.capacity() == doc1.capacity());
102150
}
103151

@@ -110,34 +158,52 @@ TEST_CASE("DynamicJsonDocument copies") {
110158
doc2 = doc1;
111159
REQUIRE(doc2.capacity() >= doc1.memoryUsage());
112160

113-
std::string json;
114-
serializeJson(doc2, json);
115-
REQUIRE(json == "{\"hello\":\"world\"}");
161+
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
116162
}
117163

118-
SECTION("Construct from StaticJsonDocument") {
119-
StaticJsonDocument<200> sdoc;
120-
deserializeJson(sdoc, "{\"hello\":\"world\"}");
164+
SECTION("Assign from StaticJsonDocument") {
165+
StaticJsonDocument<200> doc1;
166+
deserializeJson(doc1, "{\"hello\":\"world\"}");
167+
DynamicJsonDocument doc2(4096);
168+
doc2.to<JsonVariant>().set(666);
121169

122-
DynamicJsonDocument ddoc = sdoc;
170+
doc2 = doc1;
123171

124-
std::string json;
125-
serializeJson(ddoc, json);
126-
REQUIRE(json == "{\"hello\":\"world\"}");
127-
REQUIRE(ddoc.capacity() == sdoc.capacity());
172+
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
128173
}
129174

130-
SECTION("Assign from StaticJsonDocument") {
131-
DynamicJsonDocument ddoc(4096);
132-
ddoc.to<JsonVariant>().set(666);
175+
SECTION("Assign from JsonObject") {
176+
StaticJsonDocument<200> doc1;
177+
JsonObject obj = doc1.to<JsonObject>();
178+
obj["hello"] = "world";
133179

134-
StaticJsonDocument<200> sdoc;
135-
deserializeJson(sdoc, "{\"hello\":\"world\"}");
180+
DynamicJsonDocument doc2(4096);
181+
doc2 = obj;
136182

137-
ddoc = sdoc;
183+
REQUIRE_JSON(doc2, "{\"hello\":\"world\"}");
184+
REQUIRE(doc2.capacity() == 4096);
185+
}
138186

139-
std::string json;
140-
serializeJson(ddoc, json);
141-
REQUIRE(json == "{\"hello\":\"world\"}");
187+
SECTION("Assign from JsonArray") {
188+
StaticJsonDocument<200> doc1;
189+
JsonArray arr = doc1.to<JsonArray>();
190+
arr.add("hello");
191+
192+
DynamicJsonDocument doc2(4096);
193+
doc2 = arr;
194+
195+
REQUIRE_JSON(doc2, "[\"hello\"]");
196+
REQUIRE(doc2.capacity() == 4096);
197+
}
198+
199+
SECTION("Assign from JsonVariant") {
200+
StaticJsonDocument<200> doc1;
201+
deserializeJson(doc1, "42");
202+
203+
DynamicJsonDocument doc2(4096);
204+
doc2 = doc1.as<JsonVariant>();
205+
206+
REQUIRE_JSON(doc2, "42");
207+
REQUIRE(doc2.capacity() == 4096);
142208
}
143209
}

0 commit comments

Comments
 (0)
0