Copy JsonArray and JsonObject, instead of storing pointers (fixes #780)

This commit is contained in:
Benoit Blanchon
2018-09-11 16:05:56 +02:00
parent 2998a55f0b
commit b106b1ed14
52 changed files with 971 additions and 978 deletions

View File

@ -51,11 +51,14 @@ TEST_CASE("JsonArray::copyFrom()") {
JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2);
StaticJsonDocument<SIZE> doc;
JsonArray array = doc.to<JsonArray>();
char json[32];
char json[32] = "";
int source[][3] = {{1, 2, 3}, {4, 5, 6}};
CAPTURE(SIZE)
bool ok = array.copyFrom(source);
REQUIRE_FALSE(ok);
CAPTURE(doc.memoryUsage());
CHECK_FALSE(ok);
serializeJson(array, json, sizeof(json));
REQUIRE(std::string("[[1,2,3],[4,5]]") == json);

View File

@ -17,9 +17,9 @@ TEST_CASE("JsonArray::isNull()") {
REQUIRE(array.isNull() == false);
}
SECTION("returns true when allocation fails") {
StaticJsonDocument<1> doc;
JsonArray array = doc.to<JsonArray>();
REQUIRE(array.isNull() == true);
}
/* SECTION("returns true when allocation fails") {
StaticJsonDocument<1> doc;
JsonArray array = doc.to<JsonArray>();
REQUIRE(array.isNull() == true);
}*/
}

View File

@ -119,6 +119,11 @@ TEST_CASE("JsonArray::operator[]") {
REQUIRE(expectedSize == doc.memoryUsage());
}
SECTION("array[0].to<JsonObject>()") {
JsonObject obj = array[0].to<JsonObject>();
REQUIRE(obj.isNull() == false);
}
#ifdef HAS_VARIABLE_LENGTH_ARRAY
SECTION("set(VLA)") {
int i = 16;

View File

@ -17,4 +17,25 @@ TEST_CASE("DynamicJsonDocument") {
REQUIRE(json == "{\"hello\":\"world\"}");
}
SECTION("memoryUsage()") {
SECTION("starts at zero") {
REQUIRE(doc.memoryUsage() == 0);
}
SECTION("JSON_ARRAY_SIZE(0)") {
doc.to<JsonArray>();
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
}
SECTION("JSON_ARRAY_SIZE(1)") {
doc.to<JsonArray>().add(42);
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1));
}
SECTION("JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(0)") {
doc.to<JsonArray>().createNestedArray();
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(0));
}
}
}

View File

@ -10,7 +10,8 @@ TEST_CASE("JsonObject::createNestedArray()") {
JsonObject obj = doc.to<JsonObject>();
SECTION("key is a const char*") {
obj.createNestedArray("hello");
JsonArray arr = obj.createNestedArray("hello");
REQUIRE(arr.isNull() == false);
}
#ifdef HAS_VARIABLE_LENGTH_ARRAY
@ -19,7 +20,8 @@ TEST_CASE("JsonObject::createNestedArray()") {
char vla[i];
strcpy(vla, "hello");
obj.createNestedArray(vla);
JsonArray arr = obj.createNestedArray(vla);
REQUIRE(arr.isNull() == false);
}
#endif
}

View File

@ -17,9 +17,9 @@ TEST_CASE("JsonObject::isNull()") {
REQUIRE(array.isNull() == false);
}
SECTION("returns true when allocation fails") {
StaticJsonDocument<1> doc;
JsonObject array = doc.to<JsonObject>();
REQUIRE(array.isNull() == true);
}
/* SECTION("returns true when allocation fails") {
StaticJsonDocument<1> doc;
JsonObject array = doc.to<JsonObject>();
REQUIRE(array.isNull() == true);
}*/
}

View File

@ -40,4 +40,9 @@ TEST_CASE("JsonObject::begin()/end()") {
// ++it;
// REQUIRE(const_object.end() == it);
// }
SECTION("Dereferencing end() is safe") {
REQUIRE(obj.end()->key() == 0);
REQUIRE(obj.end()->value().isNull());
}
}

View File

@ -9,47 +9,64 @@
TEST_CASE("JsonObject::remove()") {
DynamicJsonDocument doc;
JsonObject obj = doc.to<JsonObject>();
obj["a"] = 0;
obj["b"] = 1;
obj["c"] = 2;
std::string result;
SECTION("SizeDecreased_WhenValuesAreRemoved") {
obj["hello"] = 1;
obj.remove("hello");
REQUIRE(0 == obj.size());
}
SECTION("SizeUntouched_WhenRemoveIsCalledWithAWrongKey") {
obj["hello"] = 1;
obj.remove("world");
REQUIRE(1 == obj.size());
}
SECTION("RemoveByIterator") {
obj["a"] = 0;
obj["b"] = 1;
obj["c"] = 2;
for (JsonObject::iterator it = obj.begin(); it != obj.end(); ++it) {
if (it->value() == 1) obj.remove(it);
SECTION("remove(key)") {
SECTION("Remove first") {
obj.remove("a");
serializeJson(obj, result);
REQUIRE("{\"b\":1,\"c\":2}" == result);
}
std::string result;
serializeJson(obj, result);
REQUIRE("{\"a\":0,\"c\":2}" == result);
SECTION("Remove middle") {
obj.remove("b");
serializeJson(obj, result);
REQUIRE("{\"a\":0,\"c\":2}" == result);
}
SECTION("Remove last") {
obj.remove("c");
serializeJson(obj, result);
REQUIRE("{\"a\":0,\"b\":1}" == result);
}
}
SECTION("remove(iterator)") {
JsonObject::iterator it = obj.begin();
SECTION("Remove first") {
obj.remove(it);
serializeJson(obj, result);
REQUIRE("{\"b\":1,\"c\":2}" == result);
}
SECTION("Remove middle") {
++it;
obj.remove(it);
serializeJson(obj, result);
REQUIRE("{\"a\":0,\"c\":2}" == result);
}
SECTION("Remove last") {
it += 2;
obj.remove(it);
serializeJson(obj, result);
REQUIRE("{\"a\":0,\"b\":1}" == result);
}
}
#ifdef HAS_VARIABLE_LENGTH_ARRAY
SECTION("key is a vla") {
obj["hello"] = 1;
int i = 16;
char vla[i];
strcpy(vla, "hello");
strcpy(vla, "b");
obj.remove(vla);
REQUIRE(0 == obj.size());
serializeJson(obj, result);
REQUIRE("{\"a\":0,\"c\":2}" == result);
}
#endif
}

View File

@ -19,9 +19,21 @@ TEST_CASE("JsonObject::size()") {
REQUIRE(1 == obj.size());
}
SECTION("doesn't increase when the smae key is added twice") {
SECTION("decreases when values are removed") {
obj.set("hello", 42);
obj.remove("hello");
REQUIRE(0 == obj.size());
}
SECTION("doesn't increase when the same key is added twice") {
obj["hello"] = 1;
obj["hello"] = 2;
REQUIRE(1 == obj.size());
}
SECTION("doesn't decrease when another key is removed") {
obj["hello"] = 1;
obj.remove("world");
REQUIRE(1 == obj.size());
}
}

View File

@ -160,6 +160,12 @@ TEST_CASE("JsonObject::operator[]") {
REQUIRE(obj[null] == 0);
}
SECTION("obj[key].to<JsonArray>()") {
JsonArray arr = obj["hello"].to<JsonArray>();
REQUIRE(arr.isNull() == false);
}
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \
!defined(SUBSCRIPT_CONFLICTS_WITH_BUILTIN_OPERATOR)
SECTION("obj[VLA] = str") {

View File

@ -5,6 +5,7 @@
add_executable(JsonVariantTests
as.cpp
compare.cpp
copy.cpp
is.cpp
isnull.cpp
or.cpp

View File

@ -12,223 +12,150 @@ TEST_CASE("JsonVariant::as()") {
DynamicJsonDocument doc;
JsonVariant variant = doc.to<JsonVariant>();
SECTION("DoubleAsBool") {
SECTION("not set") {
REQUIRE(false == variant.as<bool>());
REQUIRE(0 == variant.as<int>());
REQUIRE(0.0f == variant.as<float>());
REQUIRE(0 == variant.as<char*>());
REQUIRE("null" == variant.as<std::string>());
}
SECTION("set(4.2)") {
variant.set(4.2);
REQUIRE(variant.as<bool>());
REQUIRE(0 == variant.as<const char*>());
REQUIRE(variant.as<std::string>() == "4.2");
REQUIRE(variant.as<long>() == 4L);
REQUIRE(variant.as<unsigned>() == 4U);
}
SECTION("DoubleAsCstr") {
variant.set(4.2);
REQUIRE_FALSE(variant.as<const char*>());
}
SECTION("DoubleAsString") {
variant.set(4.2);
REQUIRE(std::string("4.2") == variant.as<std::string>());
}
SECTION("DoubleAsLong") {
variant.set(4.2);
REQUIRE(4L == variant.as<long>());
}
SECTION("DoubleAsUnsigned") {
variant.set(4.2);
REQUIRE(4U == variant.as<unsigned>());
}
SECTION("DoubleZeroAsBool") {
SECTION("set(0.0)") {
variant.set(0.0);
REQUIRE_FALSE(variant.as<bool>());
REQUIRE(variant.as<bool>() == false);
REQUIRE(variant.as<long>() == 0L);
}
SECTION("DoubleZeroAsLong") {
variant.set(0.0);
REQUIRE(0L == variant.as<long>());
}
SECTION("FalseAsBool") {
SECTION("set(false)") {
variant.set(false);
REQUIRE_FALSE(variant.as<bool>());
REQUIRE(false == variant.as<bool>());
REQUIRE(variant.as<double>() == 0.0);
REQUIRE(variant.as<long>() == 0L);
REQUIRE(variant.as<std::string>() == "false");
}
SECTION("FalseAsDouble") {
variant.set(false);
REQUIRE(0.0 == variant.as<double>());
}
SECTION("FalseAsLong") {
variant.set(false);
REQUIRE(0L == variant.as<long>());
}
SECTION("FalseAsString") {
variant.set(false);
REQUIRE(std::string("false") == variant.as<std::string>());
}
SECTION("TrueAsBool") {
SECTION("set(true)") {
variant.set(true);
REQUIRE(variant.as<bool>());
REQUIRE(variant.as<double>() == 1.0);
REQUIRE(variant.as<long>() == 1L);
REQUIRE(variant.as<std::string>() == "true");
}
SECTION("TrueAsDouble") {
variant.set(true);
REQUIRE(1.0 == variant.as<double>());
}
SECTION("TrueAsLong") {
variant.set(true);
REQUIRE(1L == variant.as<long>());
}
SECTION("TrueAsString") {
variant.set(true);
REQUIRE(std::string("true") == variant.as<std::string>());
}
SECTION("LongAsBool") {
SECTION("set(42L)") {
variant.set(42L);
REQUIRE(variant.as<bool>());
REQUIRE(variant.as<bool>() == true);
REQUIRE(variant.as<double>() == 42.0);
REQUIRE(variant.as<std::string>() == "42");
}
SECTION("LongZeroAsBool") {
variant.set(0L);
REQUIRE_FALSE(variant.as<bool>());
}
SECTION("PositiveLongAsDouble") {
variant.set(42L);
REQUIRE(42.0 == variant.as<double>());
}
SECTION("NegativeLongAsDouble") {
SECTION("set(-42L)") {
variant.set(-42L);
REQUIRE(-42.0 == variant.as<double>());
REQUIRE(variant.as<double>() == -42.0);
REQUIRE(variant.as<std::string>() == "-42");
}
SECTION("LongAsString") {
variant.set(42L);
REQUIRE(std::string("42") == variant.as<std::string>());
}
SECTION("LongZeroAsDouble") {
SECTION("set(0L)") {
variant.set(0L);
REQUIRE(0.0 == variant.as<double>());
SECTION("as<bool>()") {
REQUIRE(false == variant.as<bool>());
}
SECTION("as<double>()") {
REQUIRE(variant.as<double>() == 0.0);
}
}
SECTION("NullAsBool") {
SECTION("set(null)") {
variant.set(null);
REQUIRE_FALSE(variant.as<bool>());
REQUIRE(variant.as<bool>() == false);
REQUIRE(variant.as<double>() == 0.0);
REQUIRE(variant.as<long>() == 0L);
REQUIRE(variant.as<std::string>() == "null");
}
SECTION("NullAsDouble") {
variant.set(null);
REQUIRE(0.0 == variant.as<double>());
}
SECTION("NullAsLong") {
variant.set(null);
REQUIRE(0L == variant.as<long>());
}
SECTION("NullAsString") {
variant.set(null);
REQUIRE(std::string("null") == variant.as<std::string>());
}
SECTION("NumberStringAsBool") {
SECTION("set(\"42\")") {
variant.set("42");
REQUIRE(variant.as<bool>());
REQUIRE(variant.as<long>() == 42L);
}
SECTION("NumberStringAsLong") {
variant.set("42");
REQUIRE(42L == variant.as<long>());
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
SECTION("NumberStringAsInt64Negative") {
variant.set("-9223372036854775808");
REQUIRE(-9223372036854775807 - 1 == variant.as<long long>());
}
SECTION("NumberStringAsInt64Positive") {
variant.set("9223372036854775807");
REQUIRE(9223372036854775807 == variant.as<long long>());
}
#endif
SECTION("RandomStringAsBool") {
SECTION("set(\"hello\")") {
variant.set("hello");
REQUIRE_FALSE(variant.as<bool>());
REQUIRE(variant.as<bool>() == false);
REQUIRE(variant.as<long>() == 0L);
REQUIRE(variant.as<const char*>() == std::string("hello"));
REQUIRE(variant.as<char*>() == std::string("hello"));
REQUIRE(variant.as<std::string>() == std::string("hello"));
}
SECTION("RandomStringAsLong") {
variant.set("hello");
REQUIRE(0L == variant.as<long>());
}
SECTION("RandomStringAsConstCharPtr") {
variant.set("hello");
REQUIRE(std::string("hello") == variant.as<const char*>());
}
SECTION("RandomStringAsCharPtr") {
variant.set("hello");
REQUIRE(std::string("hello") == variant.as<char*>());
}
SECTION("RandomStringAsString") {
variant.set("hello");
REQUIRE(std::string("hello") == variant.as<std::string>());
}
SECTION("TrueStringAsBool") {
SECTION("set(\"true\")") {
variant.set("true");
REQUIRE(variant.as<bool>());
REQUIRE(variant.as<long>() == 1L);
}
SECTION("TrueStringAsLong") {
variant.set("true");
REQUIRE(1L == variant.as<long>());
}
SECTION("ObjectAsString") {
DynamicJsonDocument doc2;
JsonObject obj = doc2.to<JsonObject>();
SECTION("to<JsonObject>()") {
JsonObject obj = variant.to<JsonObject>();
obj["key"] = "value";
variant.set(obj);
REQUIRE(std::string("{\"key\":\"value\"}") == variant.as<std::string>());
SECTION("as<std::string>()") {
REQUIRE(variant.as<std::string>() == std::string("{\"key\":\"value\"}"));
}
SECTION("ObjectAsJsonObject") {
JsonObject o = variant.as<JsonObject>();
REQUIRE(o.size() == 1);
REQUIRE(o["key"] == std::string("value"));
}
}
SECTION("ArrayAsString") {
DynamicJsonDocument doc2;
JsonArray arr = doc2.to<JsonArray>();
SECTION("to<JsonArray>()") {
JsonArray arr = variant.to<JsonArray>();
arr.add(4);
arr.add(2);
variant.set(arr);
REQUIRE(std::string("[4,2]") == variant.as<std::string>());
SECTION("as<std::string>()") {
REQUIRE(variant.as<std::string>() == std::string("[4,2]"));
}
SECTION("as<JsonArray>()") {
JsonArray a = variant.as<JsonArray>();
REQUIRE(a.size() == 2);
REQUIRE(a[0] == 4);
REQUIRE(a[1] == 2);
}
}
SECTION("ArrayAsJsonArray") {
DynamicJsonDocument doc2;
JsonArray arr = doc2.to<JsonArray>();
variant.set(arr);
REQUIRE(arr == variant.as<JsonArray>());
REQUIRE(arr == variant.as<JsonArray>()); // <- shorthand
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
SECTION("Smallest int64 negative") {
variant.set("-9223372036854775808");
REQUIRE(variant.as<long long>() == -9223372036854775807 - 1);
}
SECTION("ObjectAsJsonObject") {
DynamicJsonDocument doc2;
JsonObject obj = doc2.to<JsonObject>();
variant.set(obj);
REQUIRE(obj == variant.as<JsonObject>());
REQUIRE(obj == variant.as<JsonObject>()); // <- shorthand
SECTION("Biggerst int64 positive") {
variant.set("9223372036854775807");
REQUIRE(variant.as<long long>() == 9223372036854775807);
}
#endif
}

View File

@ -265,13 +265,11 @@ TEST_CASE("JsonVariant comparisons") {
}
SECTION("ArrayInVariant") {
DynamicJsonDocument docArr1, docArr2;
JsonArray array1 = docArr1.to<JsonArray>();
JsonArray array2 = docArr2.to<JsonArray>();
JsonArray array1 = variant1.to<JsonArray>();
JsonArray array2 = variant2.to<JsonArray>();
variant1.set(array1);
variant2.set(array1);
variant3.set(array2);
array1.add(42);
array2.add(42);
REQUIRE(variant1 == variant2);
REQUIRE_FALSE(variant1 != variant2);
@ -281,13 +279,11 @@ TEST_CASE("JsonVariant comparisons") {
}
SECTION("ObjectInVariant") {
DynamicJsonDocument docObj1, docObj2;
JsonObject obj1 = docObj1.to<JsonObject>();
JsonObject obj2 = docObj2.to<JsonObject>();
JsonObject obj1 = variant1.to<JsonObject>();
JsonObject obj2 = variant2.to<JsonObject>();
variant1.set(obj1);
variant2.set(obj1);
variant3.set(obj2);
obj1["hello"] = "world";
obj2["hello"] = "world";
REQUIRE(variant1 == variant2);
REQUIRE_FALSE(variant1 != variant2);

84
test/JsonVariant/copy.cpp Normal file
View File

@ -0,0 +1,84 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("JsonVariant::set(JsonVariant)") {
DynamicJsonDocument doc1;
DynamicJsonDocument doc2;
JsonVariant var1 = doc1.to<JsonVariant>();
JsonVariant var2 = doc2.to<JsonVariant>();
SECTION("stores JsonArray by copy") {
JsonArray arr = doc2.to<JsonArray>();
arr.add(42);
var1.set(doc2.as<JsonVariant>());
arr[0] = 666;
REQUIRE(var1.as<std::string>() == "[42]");
}
SECTION("stores JsonObject by copy") {
JsonObject obj = doc2.to<JsonObject>();
obj["value"] = 42;
var1.set(doc2.as<JsonVariant>());
obj["value"] = 666;
REQUIRE(var1.as<std::string>() == "{\"value\":42}");
}
SECTION("stores const char* by reference") {
var1.set("hello!!");
var2.set(var1);
REQUIRE(doc1.memoryUsage() == 0);
REQUIRE(doc2.memoryUsage() == 0);
}
SECTION("stores char* by copy") {
char str[] = "hello!!";
var1.set(str);
var2.set(var1);
REQUIRE(doc1.memoryUsage() == 8);
REQUIRE(doc2.memoryUsage() == 8);
}
SECTION("stores std::string by copy") {
var1.set(std::string("hello!!"));
var2.set(var1);
REQUIRE(doc1.memoryUsage() == 8);
REQUIRE(doc2.memoryUsage() == 8);
}
SECTION("stores Serialized<const char*> by reference") {
var1.set(serialized("hello!!", 8));
var2.set(var1);
REQUIRE(doc1.memoryUsage() == 0);
REQUIRE(doc2.memoryUsage() == 0);
}
SECTION("stores Serialized<char*> by copy") {
char str[] = "hello!!";
var1.set(serialized(str, 8));
var2.set(var1);
REQUIRE(doc1.memoryUsage() == 8);
REQUIRE(doc2.memoryUsage() == 8);
}
SECTION("stores Serialized<std::string> by copy") {
var1.set(serialized(std::string("hello!!!")));
var2.set(var1);
REQUIRE(doc1.memoryUsage() == 8);
REQUIRE(doc2.memoryUsage() == 8);
}
}

View File

@ -35,13 +35,13 @@ TEST_CASE("JsonVariant::isNull()") {
REQUIRE(variant.isNull() == false);
}
SECTION("return true when InvalidArray") {
variant.set(JsonArray());
REQUIRE(variant.isNull() == true);
}
SECTION("return true when InvalidObject") {
variant.set(JsonObject());
REQUIRE(variant.isNull() == true);
}
/* SECTION("return true when InvalidArray") {
variant.set(JsonArray());
REQUIRE(variant.isNull() == true);
}
*/
/* SECTION("return true when InvalidObject") {
variant.set(JsonObject());
REQUIRE(variant.isNull() == true);
}*/
}

View File

@ -23,9 +23,7 @@ TEST_CASE("JsonVariant::operator[]") {
}
SECTION("The JsonVariant is a JsonArray") {
DynamicJsonDocument doc2;
JsonArray array = doc2.to<JsonArray>();
var.set(array);
JsonArray array = var.to<JsonArray>();
SECTION("get value") {
array.add("element at index 0");
@ -62,9 +60,7 @@ TEST_CASE("JsonVariant::operator[]") {
}
SECTION("The JsonVariant is a JsonObject") {
DynamicJsonDocument doc2;
JsonObject object = doc2.to<JsonObject>();
var.set(object);
JsonObject object = var.to<JsonObject>();
SECTION("get value") {
object["a"] = "element at key \"a\"";
@ -92,6 +88,11 @@ TEST_CASE("JsonVariant::operator[]") {
REQUIRE(1 == var.size());
REQUIRE(std::string("world") == var["hello"]);
}
SECTION("var[key].to<JsonArray>()") {
JsonArray arr = var["hello"].to<JsonArray>();
REQUIRE(arr.isNull() == false);
}
}
#if defined(HAS_VARIABLE_LENGTH_ARRAY) && \

View File

@ -8,47 +8,39 @@
TEST_CASE("JsonVariant undefined") {
JsonVariant variant;
SECTION("AsLongReturns0") {
SECTION("as<long>()") {
REQUIRE(0 == variant.as<long>());
}
SECTION("AsUnsignedReturns0") {
SECTION("as<unsigned>()") {
REQUIRE(0 == variant.as<unsigned>());
}
SECTION("AsStringReturnsNull") {
SECTION("as<char*>()") {
REQUIRE(0 == variant.as<char*>());
}
SECTION("AsDoubleReturns0") {
SECTION("as<double>()") {
REQUIRE(0 == variant.as<double>());
}
SECTION("AsBoolReturnsFalse") {
SECTION("as<bool>()") {
REQUIRE(false == variant.as<bool>());
}
SECTION("AsArrayReturnInvalid") {
REQUIRE(JsonArray() == variant.as<JsonArray>());
SECTION("as<JsonArray>()") {
REQUIRE(variant.as<JsonArray>().isNull());
}
SECTION("AsConstArrayReturnInvalid") {
REQUIRE(JsonArray() == variant.as<const JsonArray>());
SECTION("as<const JsonArray>()") {
REQUIRE(variant.as<const JsonArray>().isNull());
}
SECTION("AsObjectReturnInvalid") {
REQUIRE(JsonObject() == variant.as<JsonObject>());
SECTION("as<JsonObject>()") {
REQUIRE(variant.as<JsonObject>().isNull());
}
SECTION("AsConstObjectReturnInvalid") {
REQUIRE(JsonObject() == variant.as<const JsonObject>());
}
SECTION("AsArrayWrapperReturnInvalid") {
REQUIRE(JsonArray() == variant.as<JsonArray>());
}
SECTION("AsObjectWrapperReturnInvalid") {
REQUIRE(JsonObject() == variant.as<JsonObject>());
SECTION("as<const JsonObject>()") {
REQUIRE(variant.as<const JsonObject>().isNull());
}
}