Added StaticJsonDocument and DynamicJsonDocument.

Removed StaticJsonArray and DynamicJsonArray.
Removed StaticJsonObject and DynamicJsonObject.
Removed StaticJsonVariant and DynamicJsonVariant.
This commit is contained in:
Benoit Blanchon
2018-04-17 21:27:45 +02:00
parent a13b9e8bdc
commit 1feb92679d
100 changed files with 1696 additions and 1844 deletions

View File

@ -6,9 +6,7 @@ HEAD
* Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693) * Fixed `JsonBuffer::parse()` not respecting nesting limit correctly (issue #693)
* Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu) * Fixed inconsistencies in nesting level counting (PR #695 from Zhenyu Wu)
* Added `DynamicJsonArray` and `StaticJsonArray` * Added `DynamicJsonDocument` and `StaticJsonDocument`
* Added `DynamicJsonObject` and `StaticJsonObject`
* Added `DynamicJsonVariant` and `StaticJsonVariant`
* Added `deserializeJson()` * Added `deserializeJson()`
* Added `serializeJson()` and `serializeJsonPretty()` * Added `serializeJson()` and `serializeJsonPretty()`
* Added `measureJson()` and `measureJsonPretty()` * Added `measureJson()` and `measureJsonPretty()`
@ -37,11 +35,12 @@ HEAD
> New code: > New code:
> >
> ```c++ > ```c++
> DynamicJsonObject obj; > DynamicJsonDocument doc;
> JsonError error = deserializeJson(obj, json); > JsonError error = deserializeJson(doc, json);
> if (error) { > if (error) {
> >
> } > }
> JsonObject& obj = doc.as<JsonObject>();
> ``` > ```
> >
> #### Serialization > #### Serialization
@ -58,9 +57,10 @@ HEAD
> New code: > New code:
> >
> ```c++ > ```c++
> DynamicJsonObject obj; > DynamicJsonDocument obj;
> JsonObject& obj = doc.to<JsonObject>();
> obj["key"] = "value"; > obj["key"] = "value";
> serializeJson(obj, Serial); > serializeJson(doc, Serial);
> ``` > ```
v5.13.1 v5.13.1

View File

@ -59,9 +59,10 @@ Here is a program that parses a JSON document with ArduinoJson.
```c++ ```c++
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
DynamicJsonObject root; DynamicJsonDocument doc;
deserializeJson(root, json); deserializeJson(doc, json);
JsonObject& root = doc.as<JsonObject>();
const char* sensor = root["sensor"]; const char* sensor = root["sensor"];
long time = root["time"]; long time = root["time"];
double latitude = root["data"][0]; double latitude = root["data"][0];
@ -75,7 +76,9 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
Here is a program that generates a JSON document with ArduinoJson: Here is a program that generates a JSON document with ArduinoJson:
```c++ ```c++
DynamicJsonObject root; DynamicJsonDocument doc;
JsonObject& root = doc.to<JsonObject>();
root["sensor"] = "gps"; root["sensor"] = "gps";
root["time"] = 1351824120; root["time"] = 1351824120;
@ -83,7 +86,7 @@ JsonArray& data = root.createNestedArray("data");
data.add(48.756080); data.add(48.756080);
data.add(2.302038); data.add(2.302038);
serializeJson(root, Serial); serializeJson(doc, Serial);
// This prints: // This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
``` ```

View File

@ -29,17 +29,19 @@ void loadConfiguration(const char *filename, Config &config) {
// Open file for reading // Open file for reading
File file = SD.open(filename); File file = SD.open(filename);
// Allocate the memory pool on the stack. // Allocate the document on the stack.
// Don't forget to change the capacity to match your JSON document. // Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
StaticJsonObject<512> root; StaticJsonDocument<512> doc;
// Parse the root object
JsonError error = deserializeJson(root, file);
// Deserialize the JSON document
JsonError error = deserializeJson(doc, file);
if (error) if (error)
Serial.println(F("Failed to read file, using default configuration")); Serial.println(F("Failed to read file, using default configuration"));
// Get the root object in the document
JsonObject &root = doc.as<JsonObject>();
// Copy values from the JsonObject to the Config // Copy values from the JsonObject to the Config
config.port = root["port"] | 2731; config.port = root["port"] | 2731;
strlcpy(config.hostname, // <- destination strlcpy(config.hostname, // <- destination
@ -62,17 +64,20 @@ void saveConfiguration(const char *filename, const Config &config) {
return; return;
} }
// Allocate the memory pool on the stack // Allocate the document on the stack.
// Don't forget to change the capacity to match your JSON document. // Don't forget to change the capacity to match your requirements.
// Use https://arduinojson.org/assistant/ to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
StaticJsonObject<256> root; StaticJsonDocument<256> doc;
// Set the values // Make our document contain an object
JsonObject &root = doc.to<JsonObject>();
// Set the values in the object
root["hostname"] = config.hostname; root["hostname"] = config.hostname;
root["port"] = config.port; root["port"] = config.port;
// Serialize JSON to file // Serialize JSON to file
if (serializeJson(root, file) == 0) { if (serializeJson(doc, file) == 0) {
Serial.println(F("Failed to write to file")); Serial.println(F("Failed to write to file"));
} }

View File

@ -11,17 +11,20 @@ void setup() {
Serial.begin(9600); Serial.begin(9600);
while (!Serial) continue; while (!Serial) continue;
// Root JSON object // The JSON document
// //
// Inside the brackets, 200 is the size of the memory pool in bytes. // Inside the brackets, 200 is the RAM allocated to this document.
// Don't forget to change this value to match your JSON document. // Don't forget to change this value to match your requirement.
// Use arduinojson.org/assistant to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
StaticJsonObject<200> root; StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be // StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap. // replaced by DynamicJsonDocument which allocates in the heap.
// //
// DynamicJsonObject root(200); // DynamicJsonDocument doc(200);
// Make our document be an object
JsonObject& root = doc.to<JsonObject>();
// Add values in the object // Add values in the object
// //
@ -30,10 +33,8 @@ void setup() {
root["sensor"] = "gps"; root["sensor"] = "gps";
root["time"] = 1351824120; root["time"] = 1351824120;
// Add a nested array. // Add an array.
// //
// It's also possible to create the array separately and add it to the
// JsonObject but it's less efficient.
JsonArray& data = root.createNestedArray("data"); JsonArray& data = root.createNestedArray("data");
data.add(48.756080); data.add(48.756080);
data.add(2.302038); data.add(2.302038);

View File

@ -70,19 +70,21 @@ void setup() {
return; return;
} }
// Allocate JsonBuffer // Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60; const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
DynamicJsonObject root(capacity); DynamicJsonDocument doc(capacity);
// Parse JSON object // Parse JSON object
JsonError error = deserializeJson(root, client); JsonError error = deserializeJson(doc, client);
if (error) { if (error) {
Serial.println(F("Parsing failed!")); Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return; return;
} }
// Extract values // Extract values
JsonObject& root = doc.as<JsonObject>();
Serial.println(F("Response:")); Serial.println(F("Response:"));
Serial.println(root["sensor"].as<char*>()); Serial.println(root["sensor"].as<char*>());
Serial.println(root["time"].as<char*>()); Serial.println(root["time"].as<char*>());

View File

@ -16,12 +16,12 @@ void setup() {
// Inside the brackets, 200 is the size of the memory pool in bytes. // Inside the brackets, 200 is the size of the memory pool in bytes.
// Don't forget to change this value to match your JSON document. // Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
StaticJsonObject<200> root; StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be // StaticJsonDocument<N> allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap. // replaced by DynamicJsonObject which allocates in the heap.
// //
// DynamicJsonObject root(200); // DynamicJsonObject doc(200);
// JSON input string. // JSON input string.
// //
@ -31,23 +31,23 @@ void setup() {
char json[] = char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
// Root of the object tree. // Deserialize the JSON document
// JsonError error = deserializeJson(doc, json);
// It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope.
JsonError error = deserializeJson(root, json);
// Test if parsing succeeds. // Test if parsing succeeds.
if (error) { if (error) {
Serial.println("deserializeJson() failed"); Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return; return;
} }
// Get the root object in the document
JsonObject& root = doc.as<JsonObject>();
// Fetch values. // Fetch values.
// //
// Most of the time, you can rely on the implicit casts. // Most of the time, you can rely on the implicit casts.
// In other case, you can do root["time"].as<long>(); // In other case, you can do doc["time"].as<long>();
const char* sensor = root["sensor"]; const char* sensor = root["sensor"];
long time = root["time"]; long time = root["time"];
double latitude = root["data"][0]; double latitude = root["data"][0];

View File

@ -51,9 +51,12 @@ void loop() {
// Read the request (we ignore the content in this example) // Read the request (we ignore the content in this example)
while (client.available()) client.read(); while (client.available()) client.read();
// Allocate the root JsonObject // Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
StaticJsonObject<500> root; StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject& root = doc.to<JsonObject>();
// Create the "analog" array // Create the "analog" array
JsonArray& analogValues = root.createNestedArray("analog"); JsonArray& analogValues = root.createNestedArray("analog");

View File

@ -43,9 +43,12 @@ void setup() {
} }
void loop() { void loop() {
// Allocate the root JsonObject // Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
StaticJsonObject<500> root; StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject& root = doc.to<JsonObject>();
// Create the "analog" array // Create the "analog" array
JsonArray& analogValues = root.createNestedArray("analog"); JsonArray& analogValues = root.createNestedArray("analog");

View File

@ -12,17 +12,17 @@ void setup() {
Serial.begin(9600); Serial.begin(9600);
while (!Serial) continue; while (!Serial) continue;
// Root JSON object // Allocate the JSON document
// //
// Inside the brackets, 200 is the size of the memory pool in bytes. // Inside the brackets, 200 is the size of the memory pool in bytes.
// Don't forget to change this value to match your JSON document. // Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity. // Use arduinojson.org/assistant to compute the capacity.
StaticJsonObject<200> root; StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be // StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap. // replaced by DynamicJsonObject which allocates in the heap.
// //
// DynamicJsonObject root(200); // DynamicJsonObject doc(200);
// MessagePack input string. // MessagePack input string.
// //
@ -40,23 +40,27 @@ void setup() {
// "data": [48.75608, 2.302038] // "data": [48.75608, 2.302038]
// } // }
// Root of the object tree. // doc of the object tree.
// //
// It's a reference to the JsonObject, the actual bytes are inside the // It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree. // JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope. // Memory is freed when jsonBuffer goes out of scope.
MsgPackError error = deserializeMsgPack(root, input); MsgPackError error = deserializeMsgPack(doc, input);
// Test if parsing succeeds. // Test if parsing succeeds.
if (error) { if (error) {
Serial.println("deserializeMsgPack() failed"); Serial.print("deserializeMsgPack() failed: ");
Serial.println(error.c_str());
return; return;
} }
// Get the root object in the document
JsonObject& root = doc.as<JsonObject>();
// Fetch values. // Fetch values.
// //
// Most of the time, you can rely on the implicit casts. // Most of the time, you can rely on the implicit casts.
// In other case, you can do root["time"].as<long>(); // In other case, you can do doc["time"].as<long>();
const char* sensor = root["sensor"]; const char* sensor = root["sensor"];
long time = root["time"]; long time = root["time"];
double latitude = root["data"][0]; double latitude = root["data"][0];

View File

@ -14,33 +14,34 @@
void setup() { void setup() {
#ifdef PROGMEM // <- check that Flash strings are supported #ifdef PROGMEM // <- check that Flash strings are supported
DynamicJsonObject root; DynamicJsonDocument doc;
// You can use a Flash String as your JSON input. // You can use a Flash String as your JSON input.
// WARNING: the content of the Flash String will be duplicated in the // WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer. // JsonBuffer.
deserializeJson(root, F("{\"sensor\":\"gps\",\"time\":1351824120," deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
"\"data\":[48.756080,2.302038]}")); "\"data\":[48.756080,2.302038]}"));
JsonObject& obj = doc.as<JsonObject>();
// You can use a Flash String to get an element of a JsonObject // You can use a Flash String to get an element of a JsonObject
// No duplication is done. // No duplication is done.
long time = root[F("time")]; long time = obj[F("time")];
// You can use a Flash String to set an element of a JsonObject // You can use a Flash String to set an element of a JsonObject
// WARNING: the content of the Flash String will be duplicated in the // WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer. // JsonBuffer.
root[F("time")] = time; obj[F("time")] = time;
// You can set a Flash String to a JsonObject or JsonArray: // You can set a Flash String to a JsonObject or JsonArray:
// WARNING: the content of the Flash String will be duplicated in the // WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer. // JsonBuffer.
root["sensor"] = F("gps"); obj["sensor"] = F("gps");
// It works with RawJson too: // It works with RawJson too:
root["sensor"] = RawJson(F("\"gps\"")); obj["sensor"] = RawJson(F("\"gps\""));
// You can compare the content of a JsonVariant to a Flash String // You can compare the content of a JsonVariant to a Flash String
if (root["sensor"] == F("gps")) { if (obj["sensor"] == F("gps")) {
// ... // ...
} }

View File

@ -11,50 +11,51 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
void setup() { void setup() {
DynamicJsonObject root; DynamicJsonDocument doc;
// You can use a String as your JSON input. // You can use a String as your JSON input.
// WARNING: the content of the String will be duplicated in the JsonBuffer. // WARNING: the content of the String will be duplicated in the JsonBuffer.
String input = String input =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
deserializeJson(root, input); deserializeJson(doc, input);
JsonObject& obj = doc.as<JsonObject>();
// You can use a String to get an element of a JsonObject // You can use a String to get an element of a JsonObject
// No duplication is done. // No duplication is done.
long time = root[String("time")]; long time = obj[String("time")];
// You can use a String to set an element of a JsonObject // You can use a String to set an element of a JsonObject
// WARNING: the content of the String will be duplicated in the JsonBuffer. // WARNING: the content of the String will be duplicated in the JsonBuffer.
root[String("time")] = time; obj[String("time")] = time;
// You can get a String from a JsonObject or JsonArray: // You can get a String from a JsonObject or JsonArray:
// No duplication is done, at least not in the JsonBuffer. // No duplication is done, at least not in the JsonBuffer.
String sensor = root["sensor"]; String sensor = obj["sensor"];
// Unfortunately, the following doesn't work (issue #118): // Unfortunately, the following doesn't work (issue #118):
// sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='" // sensor = obj["sensor"]; // <- error "ambiguous overload for 'operator='"
// As a workaround, you need to replace by: // As a workaround, you need to replace by:
sensor = root["sensor"].as<String>(); sensor = obj["sensor"].as<String>();
// You can set a String to a JsonObject or JsonArray: // You can set a String to a JsonObject or JsonArray:
// WARNING: the content of the String will be duplicated in the JsonBuffer. // WARNING: the content of the String will be duplicated in the JsonBuffer.
root["sensor"] = sensor; obj["sensor"] = sensor;
// It works with RawJson too: // It works with RawJson too:
root["sensor"] = RawJson(sensor); obj["sensor"] = RawJson(sensor);
// You can also concatenate strings // You can also concatenate strings
// WARNING: the content of the String will be duplicated in the JsonBuffer. // WARNING: the content of the String will be duplicated in the JsonBuffer.
root[String("sen") + "sor"] = String("gp") + "s"; obj[String("sen") + "sor"] = String("gp") + "s";
// You can compare the content of a JsonObject with a String // You can compare the content of a JsonObject with a String
if (root["sensor"] == sensor) { if (obj["sensor"] == sensor) {
// ... // ...
} }
// Lastly, you can print the resulting JSON to a String // Lastly, you can print the resulting JSON to a String
String output; String output;
serializeJson(root, output); serializeJson(doc, output);
} }
void loop() { void loop() {

View File

@ -16,11 +16,11 @@ class memstream : public std::istream {
}; };
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonVariant variant; DynamicJsonDocument doc;
memstream json(data, size); memstream json(data, size);
JsonError error = deserializeJson(variant, json); JsonError error = deserializeJson(doc, json);
JsonVariant variant = jsonBuffer.parse(json); if (error == JsonError::Ok) {
if (!error) { JsonVariant variant = doc.as<JsonVariant>();
variant.as<std::string>(); // <- serialize to JSON variant.as<std::string>(); // <- serialize to JSON
} }
return 0; return 0;

View File

@ -3,9 +3,8 @@ as KEYWORD2
createNestedArray KEYWORD2 createNestedArray KEYWORD2
createNestedObject KEYWORD2 createNestedObject KEYWORD2
deserializeJson KEYWORD2 deserializeJson KEYWORD2
DynamicJsonArray KEYWORD1 deserializeMsgPack KEYWORD2
DynamicJsonObject KEYWORD1 DynamicJsonDocument KEYWORD1
DynamicJsonVariant KEYWORD1
get KEYWORD2 get KEYWORD2
JsonArray KEYWORD1 JsonArray KEYWORD1
JsonObject KEYWORD1 JsonObject KEYWORD1
@ -13,6 +12,5 @@ JsonVariant KEYWORD1
serializeJson KEYWORD2 serializeJson KEYWORD2
serializeJsonPretty KEYWORD2 serializeJsonPretty KEYWORD2
set KEYWORD2 set KEYWORD2
StaticJsonArray KEYWORD1 StaticJsonDocument KEYWORD1
StaticJsonObject KEYWORD1 to KEYWORD2
StaticJsonVariant KEYWORD1

View File

@ -4,18 +4,14 @@
#pragma once #pragma once
#include "ArduinoJson/DynamicJsonArray.hpp" #include "ArduinoJson/DynamicJsonDocument.hpp"
#include "ArduinoJson/DynamicJsonObject.hpp"
#include "ArduinoJson/DynamicJsonVariant.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp" #include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/StaticJsonArray.hpp" #include "ArduinoJson/StaticJsonDocument.hpp"
#include "ArduinoJson/StaticJsonObject.hpp"
#include "ArduinoJson/StaticJsonVariant.hpp"
#include "ArduinoJson/deserializeJson.hpp" #include "ArduinoJson/deserializeJson.hpp"
#include "ArduinoJson/deserializeMsgPack.hpp" #include "ArduinoJson/deserializeMsgPack.hpp"
#include "ArduinoJson/Json/Deserialization/JsonParserImpl.hpp" #include "ArduinoJson/Json/Deserialization/JsonDeserializer.hpp"
#include "ArduinoJson/Json/Serialization/JsonSerializerImpl.hpp" #include "ArduinoJson/Json/Serialization/JsonSerializer.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp" #include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp" #include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp" #include "ArduinoJson/JsonVariantImpl.hpp"

View File

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonArray : public JsonArray {
DynamicJsonBuffer _buffer;
public:
DynamicJsonArray() : JsonArray(&_buffer) {}
DynamicJsonArray(size_t capacity)
: JsonArray(&_buffer), _buffer(capacity - sizeof(JsonArray)) {}
void clear() {
Internals::List<JsonVariant>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonArray);
}
DynamicJsonBuffer& buffer() {
return _buffer;
}
};
} // namespace ArduinoJson

View File

@ -0,0 +1,83 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonVariant.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonDocument {
Internals::DynamicJsonBuffer _buffer;
JsonVariant _root;
public:
DynamicJsonDocument() {}
DynamicJsonDocument(size_t capacity) : _buffer(capacity) {}
template <typename T>
bool is() const {
return _root.is<T>();
}
template <typename T>
typename Internals::JsonVariantAs<T>::type as() const {
return _root.as<T>();
}
// JsonObject& to<JsonObject>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonObject>::value,
JsonObject&>::type
to() {
clear();
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
if (!object) return JsonObject::invalid();
_root = object;
return *object;
}
// JsonArray& to<JsonArray>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonArray>::value,
JsonArray&>::type
to() {
clear();
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
if (!array) return JsonArray::invalid();
_root = array;
return *array;
}
// JsonVariant& to<JsonVariant>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonVariant>::value,
T&>::type
to() {
clear();
return _root;
}
Internals::DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
_root = JsonVariant();
}
size_t memoryUsage() const {
return _buffer.size();
}
template <typename Visitor>
void visit(Visitor visitor) const {
return _root.visit(visitor);
}
};
} // namespace ArduinoJson

View File

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonObject.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonObject : public JsonObject {
DynamicJsonBuffer _buffer;
public:
DynamicJsonObject() : JsonObject(&_buffer) {}
DynamicJsonObject(size_t capacity)
: JsonObject(&_buffer), _buffer(capacity - sizeof(JsonObject)) {}
DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
Internals::List<JsonPair>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonObject);
}
};
} // namespace ArduinoJson

View File

@ -1,45 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonVariant : public JsonVariant {
DynamicJsonBuffer _buffer;
public:
DynamicJsonVariant() : JsonVariant() {}
DynamicJsonVariant(size_t capacity) : JsonVariant(), _buffer(capacity) {}
template <typename T>
DynamicJsonVariant& operator=(const T& value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
template <typename T>
DynamicJsonVariant& operator=(const T* value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size();
}
};
} // namespace ArduinoJson

View File

@ -0,0 +1,218 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../../JsonError.hpp"
#include "../../JsonVariant.hpp"
#include "../../Memory/JsonBuffer.hpp"
#include "../../Strings/StringWriter.hpp"
#include "../../TypeTraits/IsConst.hpp"
#include "../Encoding.hpp"
#include "./Comments.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TReader, typename TWriter>
class JsonDeserializer {
public:
JsonDeserializer(JsonBuffer *buffer, TReader reader, TWriter writer,
uint8_t nestingLimit)
: _buffer(buffer),
_reader(reader),
_writer(writer),
_nestingLimit(nestingLimit) {}
JsonError parse(JsonVariant &variant) {
skipSpacesAndComments(_reader);
switch (_reader.current()) {
case '[':
return parseArray(variant);
case '{':
return parseObject(variant);
default:
return parseValue(variant);
}
}
private:
JsonDeserializer &operator=(const JsonDeserializer &); // non-copiable
static bool eat(TReader &reader, char charToSkip) {
skipSpacesAndComments(reader);
if (reader.current() != charToSkip) return false;
reader.move();
return true;
}
FORCE_INLINE bool eat(char charToSkip) {
return eat(_reader, charToSkip);
}
JsonError parseArray(JsonVariant &variant) {
if (_nestingLimit == 0) return JsonError::TooDeep;
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return JsonError::NoMemory;
variant = array;
// Check opening braket
if (!eat('[')) return JsonError::InvalidInput;
if (eat(']')) return JsonError::Ok;
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant value;
_nestingLimit--;
JsonError error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!array->add(value)) return JsonError::NoMemory;
// 2 - More values?
if (eat(']')) return JsonError::Ok;
if (!eat(',')) return JsonError::InvalidInput;
}
}
JsonError parseObject(JsonVariant &variant) {
if (_nestingLimit == 0) return JsonError::TooDeep;
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return JsonError::NoMemory;
variant = object;
// Check opening brace
if (!eat('{')) return JsonError::InvalidInput;
if (eat('}')) return JsonError::Ok;
// Read each key value pair
for (;;) {
// 1 - Parse key
const char *key;
JsonError error = parseString(&key);
if (error) return error;
if (!eat(':')) return JsonError::InvalidInput;
// 2 - Parse value
JsonVariant value;
_nestingLimit--;
error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!object->set(key, value)) return JsonError::NoMemory;
// 3 - More keys/values?
if (eat('}')) return JsonError::Ok;
if (!eat(',')) return JsonError::InvalidInput;
}
}
JsonError parseValue(JsonVariant &variant) {
bool hasQuotes = isQuote(_reader.current());
const char *value;
JsonError error = parseString(&value);
if (error) return error;
if (hasQuotes) {
variant = value;
} else {
variant = RawJson(value);
}
return JsonError::Ok;
}
JsonError parseString(const char **result) {
typename RemoveReference<TWriter>::type::String str = _writer.startString();
skipSpacesAndComments(_reader);
char c = _reader.current();
if (isQuote(c)) { // quotes
_reader.move();
char stopChar = c;
for (;;) {
c = _reader.current();
if (c == '\0') break;
_reader.move();
if (c == stopChar) break;
if (c == '\\') {
// replace char
c = Encoding::unescapeChar(_reader.current());
if (c == '\0') return JsonError::InvalidInput;
_reader.move();
}
str.append(c);
}
} else if (canBeInNonQuotedString(c)) { // no quotes
do {
_reader.move();
str.append(c);
c = _reader.current();
} while (canBeInNonQuotedString(c));
} else {
return JsonError::InvalidInput;
}
*result = str.c_str();
if (*result == NULL) return JsonError::NoMemory;
return JsonError::Ok;
}
static inline bool isBetween(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool canBeInNonQuotedString(char c) {
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
}
static inline bool isQuote(char c) {
return c == '\'' || c == '\"';
}
JsonBuffer *_buffer;
TReader _reader;
TWriter _writer;
uint8_t _nestingLimit;
};
template <typename TJsonBuffer, typename TString, typename Enable = void>
struct JsonParserBuilder {
typedef typename StringTraits<TString>::Reader InputReader;
typedef JsonDeserializer<InputReader, TJsonBuffer &> TParser;
static TParser makeParser(TJsonBuffer *buffer, TString &json,
uint8_t nestingLimit) {
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
}
};
template <typename TJsonBuffer, typename TChar>
struct JsonParserBuilder<TJsonBuffer, TChar *,
typename EnableIf<!IsConst<TChar>::value>::type> {
typedef typename StringTraits<TChar *>::Reader TReader;
typedef StringWriter<TChar> TWriter;
typedef JsonDeserializer<TReader, TWriter> TParser;
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
uint8_t nestingLimit) {
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
}
};
template <typename TJsonBuffer, typename TString>
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
nestingLimit);
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,95 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../../JsonError.hpp"
#include "../../JsonVariant.hpp"
#include "../../Memory/JsonBuffer.hpp"
#include "../../Strings/StringWriter.hpp"
#include "../../TypeTraits/IsConst.hpp"
namespace ArduinoJson {
namespace Internals {
// Parse JSON string to create JsonArrays and JsonObjects
// This internal class is not indended to be used directly.
// Instead, use JsonBuffer.parseArray() or .parseObject()
template <typename TReader, typename TWriter>
class JsonParser {
public:
JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
uint8_t nestingLimit)
: _buffer(buffer),
_reader(reader),
_writer(writer),
_nestingLimit(nestingLimit) {}
JsonError parse(JsonArray &destination);
JsonError parse(JsonObject &destination);
JsonError parse(JsonVariant &destination);
private:
JsonParser &operator=(const JsonParser &); // non-copiable
static bool eat(TReader &, char charToSkip);
FORCE_INLINE bool eat(char charToSkip) {
return eat(_reader, charToSkip);
}
const char *parseString();
JsonError parseArray(JsonVariant &variant);
JsonError parseObject(JsonVariant &variant);
JsonError parseValue(JsonVariant &variant);
static inline bool isBetween(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool canBeInNonQuotedString(char c) {
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
}
static inline bool isQuote(char c) {
return c == '\'' || c == '\"';
}
JsonBuffer *_buffer;
TReader _reader;
TWriter _writer;
uint8_t _nestingLimit;
};
template <typename TJsonBuffer, typename TString, typename Enable = void>
struct JsonParserBuilder {
typedef typename StringTraits<TString>::Reader InputReader;
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
static TParser makeParser(TJsonBuffer *buffer, TString &json,
uint8_t nestingLimit) {
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
}
};
template <typename TJsonBuffer, typename TChar>
struct JsonParserBuilder<TJsonBuffer, TChar *,
typename EnableIf<!IsConst<TChar>::value>::type> {
typedef typename StringTraits<TChar *>::Reader TReader;
typedef StringWriter<TChar> TWriter;
typedef JsonParser<TReader, TWriter> TParser;
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
uint8_t nestingLimit) {
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
}
};
template <typename TJsonBuffer, typename TString>
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
nestingLimit);
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,166 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Encoding.hpp"
#include "Comments.hpp"
#include "JsonParser.hpp"
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
TReader &reader, char charToSkip) {
skipSpacesAndComments(reader);
if (reader.current() != charToSkip) return false;
reader.move();
return true;
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parse(JsonArray &array) {
if (_nestingLimit == 0) return JsonError::TooDeep;
// Check opening braket
if (!eat('[')) return JsonError::OpeningBracketExpected;
if (eat(']')) return JsonError::Ok;
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant value;
_nestingLimit--;
JsonError error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!array.add(value)) return JsonError::NoMemory;
// 2 - More values?
if (eat(']')) return JsonError::Ok;
if (!eat(',')) return JsonError::ClosingBracketExpected;
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parse(
JsonObject &object) {
if (_nestingLimit == 0) return JsonError::TooDeep;
// Check opening brace
if (!eat('{')) return JsonError::OpeningBraceExpected;
if (eat('}')) return JsonError::Ok;
// Read each key value pair
for (;;) {
// 1 - Parse key
const char *key = parseString();
if (!key) return JsonError::NoMemory;
if (!eat(':')) return JsonError::ColonExpected;
// 2 - Parse value
JsonVariant value;
_nestingLimit--;
JsonError error = parse(value);
_nestingLimit++;
if (error != JsonError::Ok) return error;
if (!object.set(key, value)) return JsonError::NoMemory;
// 3 - More keys/values?
if (eat('}')) return JsonError::Ok;
if (!eat(',')) return JsonError::ClosingBraceExpected;
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parse(
JsonVariant &variant) {
skipSpacesAndComments(_reader);
switch (_reader.current()) {
case '[':
return parseArray(variant);
case '{':
return parseObject(variant);
default:
return parseValue(variant);
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray(
JsonVariant &variant) {
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return JsonError::NoMemory;
variant = array;
return parse(*array);
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject(
JsonVariant &variant) {
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return JsonError::NoMemory;
variant = object;
return parse(*object);
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonError
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseValue(
JsonVariant &variant) {
bool hasQuotes = isQuote(_reader.current());
const char *value = parseString();
if (value == NULL) return JsonError::NoMemory;
if (hasQuotes) {
variant = value;
} else {
variant = RawJson(value);
}
return JsonError::Ok;
}
template <typename TReader, typename TWriter>
inline const char *
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
typename RemoveReference<TWriter>::type::String str = _writer.startString();
skipSpacesAndComments(_reader);
char c = _reader.current();
if (isQuote(c)) { // quotes
_reader.move();
char stopChar = c;
for (;;) {
c = _reader.current();
if (c == '\0') break;
_reader.move();
if (c == stopChar) break;
if (c == '\\') {
// replace char
c = Encoding::unescapeChar(_reader.current());
if (c == '\0') break;
_reader.move();
}
str.append(c);
}
} else { // no quotes
for (;;) {
if (!canBeInNonQuotedString(c)) break;
_reader.move();
str.append(c);
c = _reader.current();
}
}
return str.c_str();
}

View File

@ -16,26 +16,15 @@
#endif #endif
namespace ArduinoJson { namespace ArduinoJson {
class JsonArray;
class JsonObject;
class JsonVariant;
namespace Internals { namespace Internals {
class JsonArraySubscript;
template <typename TKey>
class JsonObjectSubscript;
template <typename Writer> template <typename Writer>
class JsonSerializer { class JsonSerializer {
public: public:
static void serialize(const JsonArray &, Writer &); template <typename TSource>
static void serialize(const JsonArraySubscript &, Writer &); static void serialize(const TSource &source, Writer &writer) {
static void serialize(const JsonObject &, Writer &); source.visit(Visitor(&writer));
template <typename TKey> }
static void serialize(const JsonObjectSubscript<TKey> &, Writer &);
static void serialize(const JsonVariant &, Writer &);
struct Visitor { struct Visitor {
Visitor(Writer *writer) : _writer(writer) {} Visitor(Writer *writer) : _writer(writer) {}
@ -44,12 +33,38 @@ class JsonSerializer {
_writer->writeFloat(value); _writer->writeFloat(value);
} }
void acceptArray(const JsonArray &value) { void acceptArray(const JsonArray &array) {
serialize(value, *_writer); _writer->beginArray();
JsonArray::const_iterator it = array.begin();
while (it != array.end()) {
it->visit(*this);
++it;
if (it == array.end()) break;
_writer->writeComma();
}
_writer->endArray();
} }
void acceptObject(const JsonObject &value) { void acceptObject(const JsonObject &object) {
serialize(value, *_writer); _writer->beginObject();
JsonObject::const_iterator it = object.begin();
while (it != object.end()) {
_writer->writeString(it->key);
_writer->writeColon();
it->value.visit(*this);
++it;
if (it == object.end()) break;
_writer->writeComma();
}
_writer->endObject();
} }
void acceptString(const char *value) { void acceptString(const char *value) {

View File

@ -1,69 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../../JsonArray.hpp"
#include "../../JsonArraySubscript.hpp"
#include "../../JsonObject.hpp"
#include "../../JsonObjectSubscript.hpp"
#include "../../JsonVariant.hpp"
#include "JsonSerializer.hpp"
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArray& array, Writer& writer) {
writer.beginArray();
JsonArray::const_iterator it = array.begin();
while (it != array.end()) {
serialize(*it, writer);
++it;
if (it == array.end()) break;
writer.writeComma();
}
writer.endArray();
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonArraySubscript& arraySubscript, Writer& writer) {
serialize(arraySubscript.as<JsonVariant>(), writer);
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObject& object, Writer& writer) {
writer.beginObject();
JsonObject::const_iterator it = object.begin();
while (it != object.end()) {
writer.writeString(it->key);
writer.writeColon();
serialize(it->value, writer);
++it;
if (it == object.end()) break;
writer.writeComma();
}
writer.endObject();
}
template <typename Writer>
template <typename TKey>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonObjectSubscript<TKey>& objectSubscript, Writer& writer) {
serialize(objectSubscript.template as<JsonVariant>(), writer);
}
template <typename Writer>
inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
const JsonVariant& variant, Writer& writer) {
variant.visit(Visitor(&writer));
}

View File

@ -180,6 +180,11 @@ class JsonArray : public Internals::ReferenceType,
} }
} }
template <typename Visitor>
void visit(Visitor visitor) const {
return visitor.acceptArray(*this);
}
private: private:
template <typename TValueRef> template <typename TValueRef>
bool set_impl(size_t index, TValueRef value) { bool set_impl(size_t index, TValueRef value) {

View File

@ -74,6 +74,11 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
return _array.set(_index, value); return _array.set(_index, value);
} }
template <typename Visitor>
void visit(Visitor visitor) const {
return _array.get<JsonVariant>(_index).visit(visitor);
}
private: private:
JsonArray& _array; JsonArray& _array;
const size_t _index; const size_t _index;

View File

@ -8,16 +8,7 @@ namespace ArduinoJson {
class JsonError { class JsonError {
public: public:
enum Code { enum Code { Ok, TooDeep, NoMemory, InvalidInput };
Ok,
OpeningBraceExpected,
ClosingBraceExpected,
OpeningBracketExpected,
ClosingBracketExpected,
ColonExpected,
TooDeep,
NoMemory
};
JsonError(Code code) : _code(code) {} JsonError(Code code) : _code(code) {}
@ -45,20 +36,12 @@ class JsonError {
switch (_code) { switch (_code) {
case Ok: case Ok:
return "Ok"; return "Ok";
case OpeningBraceExpected:
return "OpeningBraceExpected";
case ClosingBraceExpected:
return "ClosingBraceExpected";
case OpeningBracketExpected:
return "OpeningBracketExpected";
case ClosingBracketExpected:
return "ClosingBracketExpected";
case ColonExpected:
return "ColonExpected";
case TooDeep: case TooDeep:
return "TooDeep"; return "TooDeep";
case NoMemory: case NoMemory:
return "NoMemory"; return "NoMemory";
case InvalidInput:
return "InvalidInput";
default: default:
return "???"; return "???";
} }
@ -73,6 +56,11 @@ inline std::ostream& operator<<(std::ostream& s, const JsonError& e) {
s << e.c_str(); s << e.c_str();
return s; return s;
} }
inline std::ostream& operator<<(std::ostream& s, JsonError::Code c) {
s << JsonError(c).c_str();
return s;
}
#endif #endif
} // namespace ArduinoJson } // namespace ArduinoJson

View File

@ -229,6 +229,11 @@ class JsonObject : public Internals::ReferenceType,
return instance; return instance;
} }
template <typename Visitor>
void visit(Visitor visitor) const {
return visitor.acceptObject(*this);
}
private: private:
// Returns the list node that matches the specified key. // Returns the list node that matches the specified key.
template <typename TStringRef> template <typename TStringRef>

View File

@ -82,6 +82,11 @@ class JsonObjectSubscript
return _object.set(_key, value); return _object.set(_key, value);
} }
template <typename Visitor>
void visit(Visitor visitor) const {
return _object.get<JsonVariant>(_key).visit(visitor);
}
private: private:
JsonObject& _object; JsonObject& _object;
TStringRef _key; TStringRef _key;

View File

@ -151,6 +151,12 @@ class DynamicJsonBufferBase : public JsonBuffer {
Block* _head; Block* _head;
size_t _nextBlockCapacity; size_t _nextBlockCapacity;
}; };
// Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much
// more suitable for embedded systems.
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
DynamicJsonBuffer;
} // namespace Internals } // namespace Internals
#if defined(__clang__) #if defined(__clang__)
@ -160,10 +166,4 @@ class DynamicJsonBufferBase : public JsonBuffer {
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#endif #endif
// Implements a JsonBuffer with dynamic memory allocation.
// You are strongly encouraged to consider using StaticJsonBuffer which is much
// more suitable for embedded systems.
typedef Internals::DynamicJsonBufferBase<Internals::DefaultAllocator>
DynamicJsonBuffer;
} // namespace ArduinoJson } // namespace ArduinoJson

View File

@ -92,7 +92,6 @@ class StaticJsonBufferBase : public JsonBuffer {
size_t _capacity; size_t _capacity;
size_t _size; size_t _size;
}; };
} // namespace Internals
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic push #pragma clang diagnostic push
@ -118,6 +117,7 @@ class StaticJsonBuffer : public Internals::StaticJsonBufferBase {
private: private:
char _buffer[ACTUAL_CAPACITY]; char _buffer[ACTUAL_CAPACITY];
}; };
} // namespace Internals
} // namespace ArduinoJson } // namespace ArduinoJson
#if defined(__clang__) #if defined(__clang__)

View File

@ -28,40 +28,6 @@ class MsgPackDeserializer {
_writer(writer), _writer(writer),
_nestingLimit(nestingLimit) {} _nestingLimit(nestingLimit) {}
MsgPackError parse(JsonArray &array) {
uint8_t c = readOne();
size_t n;
if ((c & 0xF0) == 0x90) {
n = c & 0x0F;
} else if (c == 0xdc) {
n = readInteger<uint16_t>();
} else if (c == 0xdd) {
n = readInteger<uint32_t>();
} else {
return MsgPackError::NotAnArray;
}
return readArray(array, n);
}
MsgPackError parse(JsonObject &object) {
uint8_t c = readOne();
size_t n;
if ((c & 0xf0) == 0x80) {
n = c & 0x0f;
} else if (c == 0xde) {
n = readInteger<uint16_t>();
} else if (c == 0xdf) {
n = readInteger<uint32_t>();
} else {
return MsgPackError::NotAnObject;
}
return readObject(object, n);
}
MsgPackError parse(JsonVariant &variant) { MsgPackError parse(JsonVariant &variant) {
uint8_t c = readOne(); uint8_t c = readOne();

View File

@ -8,7 +8,7 @@ namespace ArduinoJson {
class MsgPackError { class MsgPackError {
public: public:
enum Code { Ok, NotSupported, NoMemory, NotAnArray, NotAnObject, TooDeep }; enum Code { Ok, NotSupported, NoMemory, TooDeep };
MsgPackError() {} MsgPackError() {}
@ -42,10 +42,6 @@ class MsgPackError {
return "NotSupported"; return "NotSupported";
case NoMemory: case NoMemory:
return "NoMemory"; return "NoMemory";
case NotAnArray:
return "NotAnArray";
case NotAnObject:
return "NotAnObject";
case TooDeep: case TooDeep:
return "TooDeep"; return "TooDeep";
default: default:
@ -62,6 +58,11 @@ inline std::ostream& operator<<(std::ostream& os, const MsgPackError& err) {
os << err.c_str(); os << err.c_str();
return os; return os;
} }
inline std::ostream& operator<<(std::ostream& os, MsgPackError::Code code) {
os << MsgPackError(code).c_str();
return os;
}
#endif #endif
} // namespace ArduinoJson } // namespace ArduinoJson

View File

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY>
class StaticJsonArray : public JsonArray {
StaticJsonBuffer<CAPACITY - sizeof(JsonArray)> _buffer;
public:
StaticJsonArray() : JsonArray(&_buffer) {}
void clear() {
Internals::List<JsonVariant>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonArray);
}
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
};
} // namespace ArduinoJson

View File

@ -0,0 +1,80 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY = sizeof(JsonVariant)>
class StaticJsonDocument {
Internals::StaticJsonBuffer<CAPACITY> _buffer;
JsonVariant _root;
public:
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
template <typename T>
bool is() const {
return _root.is<T>();
}
template <typename T>
typename Internals::JsonVariantAs<T>::type as() const {
return _root.as<T>();
}
// JsonObject& to<JsonObject>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonObject>::value,
JsonObject&>::type
to() {
clear();
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
if (!object) return JsonObject::invalid();
_root = object;
return *object;
}
// JsonArray& to<JsonArray>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonArray>::value,
JsonArray&>::type
to() {
clear();
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
if (!array) return JsonArray::invalid();
_root = array;
return *array;
}
// JsonVariant to<JsonVariant>()
template <typename T>
typename Internals::EnableIf<Internals::IsSame<T, JsonVariant>::value,
T&>::type
to() {
clear();
return _root;
}
void clear() {
_buffer.clear();
_root = JsonVariant();
}
size_t memoryUsage() const {
return _buffer.size();
}
template <typename Visitor>
void visit(Visitor visitor) const {
return _root.visit(visitor);
}
};
} // namespace ArduinoJson

View File

@ -1,32 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonObject.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY>
class StaticJsonObject : public JsonObject {
StaticJsonBuffer<CAPACITY - sizeof(JsonObject)> _buffer;
public:
StaticJsonObject() : JsonObject(&_buffer) {}
void clear() {
Internals::List<JsonPair>::clear();
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size() + sizeof(JsonObject);
}
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
};
} // namespace ArduinoJson

View File

@ -1,43 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
#include "Memory/StaticJsonBuffer.hpp"
namespace ArduinoJson {
template <size_t CAPACITY = sizeof(JsonVariant)>
class StaticJsonVariant : public JsonVariant {
StaticJsonBuffer<CAPACITY> _buffer;
public:
template <typename T>
StaticJsonVariant& operator=(const T& value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
template <typename T>
StaticJsonVariant& operator=(const T* value) {
_buffer.clear();
JsonVariant::operator=(value);
return *this;
}
Internals::StaticJsonBufferBase& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
}
size_t memoryUsage() const {
return _buffer.size();
}
};
} // namespace ArduinoJson

View File

@ -4,6 +4,8 @@
#pragma once #pragma once
#include <stdlib.h> // for size_t
namespace ArduinoJson { namespace ArduinoJson {
namespace Internals { namespace Internals {

View File

@ -4,43 +4,40 @@
#pragma once #pragma once
#include "Json/Deserialization/JsonParser.hpp" #include "Json/Deserialization/JsonDeserializer.hpp"
namespace ArduinoJson { namespace ArduinoJson {
// JsonError deserializeJson(TDestination& destination, TString json); // JsonError deserializeJson(TDocument& doc, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant // TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const std::string&, const String& // TString = const std::string&, const String&
template <typename TDestination, typename TString> template <typename TDocument, typename TString>
typename Internals::EnableIf<!Internals::IsArray<TString>::value, typename Internals::EnableIf<!Internals::IsArray<TString>::value,
JsonError>::type JsonError>::type
deserializeJson(TDestination &destination, const TString &json, deserializeJson(TDocument &doc, const TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear(); return Internals::makeParser(&doc.buffer(), json, nestingLimit)
return Internals::makeParser(&destination.buffer(), json, nestingLimit) .parse(doc.template to<JsonVariant>());
.parse(destination);
} }
// //
// JsonError deserializeJson(TDestination& destination, TString json); // JsonError deserializeJson(TDocument& doc, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant // TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const char*, const char[N], const FlashStringHelper* // TString = const char*, const char[N], const FlashStringHelper*
template <typename TDestination, typename TString> template <typename TDocument, typename TString>
JsonError deserializeJson( JsonError deserializeJson(
TDestination &destination, TString *json, TDocument &doc, TString *json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear(); return Internals::makeParser(&doc.buffer(), json, nestingLimit)
return Internals::makeParser(&destination.buffer(), json, nestingLimit) .parse(doc.template to<JsonVariant>());
.parse(destination);
} }
// //
// JsonError deserializeJson(TDestination& destination, TString json); // JsonError deserializeJson(TDocument& doc, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant // TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = std::istream&, Stream& // TString = std::istream&, Stream&
template <typename TDestination, typename TString> template <typename TDocument, typename TString>
JsonError deserializeJson( JsonError deserializeJson(
TDestination &destination, TString &json, TDocument &doc, TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear(); return Internals::makeParser(&doc.buffer(), json, nestingLimit)
return Internals::makeParser(&destination.buffer(), json, nestingLimit) .parse(doc.template to<JsonVariant>());
.parse(destination);
} }
} // namespace ArduinoJson } // namespace ArduinoJson

View File

@ -7,43 +7,37 @@
#include "MsgPack/MsgPackDeserializer.hpp" #include "MsgPack/MsgPackDeserializer.hpp"
namespace ArduinoJson { namespace ArduinoJson {
// MsgPackError deserializeMsgPack(TDestination& destination, TString json); // MsgPackError deserializeMsgPack(TDocument& doc, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant // TDocument = DynamicJsonArray | StaticJsonArray
// TString = const std::string&, const String& // TString = const std::string&, const String&
template <typename TDestination, typename TString> template <typename TDocument, typename TString>
typename Internals::EnableIf<!Internals::IsArray<TString>::value, typename Internals::EnableIf<!Internals::IsArray<TString>::value,
MsgPackError>::type MsgPackError>::type
deserializeMsgPack(TDestination &destination, const TString &json, deserializeMsgPack(TDocument &doc, const TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear(); return Internals::makeMsgPackDeserializer(&doc.buffer(), json, nestingLimit)
return Internals::makeMsgPackDeserializer(&destination.buffer(), json, .parse(doc.template to<JsonVariant>());
nestingLimit)
.parse(destination);
} }
// //
// MsgPackError deserializeMsgPack(TDestination& destination, TString json); // MsgPackError deserializeMsgPack(TDocument& doc, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant // TDocument = DynamicJsonArray | StaticJsonArray
// TString = const char*, const char[N], const FlashStringHelper* // TString = const char*, const char[N], const FlashStringHelper*
template <typename TDestination, typename TString> template <typename TDocument, typename TString>
MsgPackError deserializeMsgPack( MsgPackError deserializeMsgPack(
TDestination &destination, TString *json, TDocument &doc, TString *json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear(); return Internals::makeMsgPackDeserializer(&doc.buffer(), json, nestingLimit)
return Internals::makeMsgPackDeserializer(&destination.buffer(), json, .parse(doc.template to<JsonVariant>());
nestingLimit)
.parse(destination);
} }
// //
// MsgPackError deserializeMsgPack(TDestination& destination, TString json); // MsgPackError deserializeMsgPack(TDocument& doc, TString json);
// TDestination = JsonArray, JsonObject, JsonVariant // TDocument = DynamicJsonArray | StaticJsonArray
// TString = std::istream&, Stream& // TString = std::istream&, Stream&
template <typename TDestination, typename TString> template <typename TDocument, typename TString>
MsgPackError deserializeMsgPack( MsgPackError deserializeMsgPack(
TDestination &destination, TString &json, TDocument &doc, TString &json,
uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) { uint8_t nestingLimit = ARDUINOJSON_DEFAULT_NESTING_LIMIT) {
destination.clear(); return Internals::makeMsgPackDeserializer(&doc.buffer(), json, nestingLimit)
return Internals::makeMsgPackDeserializer(&destination.buffer(), json, .parse(doc.template to<JsonVariant>());
nestingLimit)
.parse(destination);
} }
} // namespace ArduinoJson } // namespace ArduinoJson

View File

@ -68,7 +68,7 @@ add_subdirectory(DynamicJsonBuffer)
add_subdirectory(IntegrationTests) add_subdirectory(IntegrationTests)
add_subdirectory(JsonArray) add_subdirectory(JsonArray)
add_subdirectory(JsonObject) add_subdirectory(JsonObject)
add_subdirectory(JsonParser) add_subdirectory(JsonDeserializer)
add_subdirectory(JsonSerializer) add_subdirectory(JsonSerializer)
add_subdirectory(JsonVariant) add_subdirectory(JsonVariant)
add_subdirectory(JsonWriter) add_subdirectory(JsonWriter)

View File

@ -18,8 +18,7 @@ std::stringstream allocatorLog;
struct SpyingAllocator : DefaultAllocator { struct SpyingAllocator : DefaultAllocator {
void* allocate(size_t n) { void* allocate(size_t n) {
allocatorLog << static_cast<const char*>("A") allocatorLog << "A" << (n - DynamicJsonBuffer::EmptyBlockSize);
<< (n - DynamicJsonBuffer::EmptyBlockSize);
return DefaultAllocator::allocate(n); return DefaultAllocator::allocate(n);
} }
void deallocate(void* p) { void deallocate(void* p) {

View File

@ -23,19 +23,9 @@ TEST_CASE("DynamicJsonBuffer no memory") {
} }
// TODO: uncomment // TODO: uncomment
// SECTION("parseArray()") { // SECTION("deserializeJson()") {
// char json[] = "[{}]";
// DynamicJsonArray arr;
// JsonError err = deserializeJson(arr, json);
// REQUIRE(err != JsonError::Ok);
// }
// TODO: uncomment
// SECTION("parseObject()") {
// char json[] = "{[]}"; // char json[] = "{[]}";
// DynamicJsonObject obj; // DynamicJsonDocument obj;
// JsonError err = deserializeJson(obj, json); // JsonError err = deserializeJson(obj, json);

View File

@ -2,9 +2,11 @@
// Copyright Benoit Blanchon 2014-2018 // Copyright Benoit Blanchon 2014-2018
// MIT License // MIT License
#include <ArduinoJson.h> #include <ArduinoJson/Memory/DynamicJsonBuffer.hpp>
#include <catch.hpp> #include <catch.hpp>
using namespace ArduinoJson::Internals;
TEST_CASE("DynamicJsonBuffer::size()") { TEST_CASE("DynamicJsonBuffer::size()") {
DynamicJsonBuffer buffer; DynamicJsonBuffer buffer;

View File

@ -2,9 +2,11 @@
// Copyright Benoit Blanchon 2014-2018 // Copyright Benoit Blanchon 2014-2018
// MIT License // MIT License
#include <ArduinoJson.h> #include <ArduinoJson/Memory/DynamicJsonBuffer.hpp>
#include <catch.hpp> #include <catch.hpp>
using namespace ArduinoJson::Internals;
TEST_CASE("DynamicJsonBuffer::startString()") { TEST_CASE("DynamicJsonBuffer::startString()") {
SECTION("WorksWhenBufferIsBigEnough") { SECTION("WorksWhenBufferIsBigEnough") {
DynamicJsonBuffer jsonBuffer(6); DynamicJsonBuffer jsonBuffer(6);

View File

@ -6,10 +6,10 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("Gbathree") { TEST_CASE("Gbathree") {
DynamicJsonObject _object; DynamicJsonDocument doc;
JsonError error = deserializeJson( JsonError error = deserializeJson(
_object, doc,
"{\"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0," "{\"protocol_name\":\"fluorescence\",\"repeats\":1,\"wait\":0,"
"\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_" "\"averages\":1,\"measurements\":3,\"meas2_light\":15,\"meas1_"
"baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":" "baseline\":0,\"act_light\":20,\"pulsesize\":25,\"pulsedistance\":"
@ -20,67 +20,68 @@ TEST_CASE("Gbathree") {
"\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15," "\"measlights\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,"
"15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15]," "15,15]],\"measlights2\":[[15,15,15,15],[15,15,15,15],[15,15,15,15],"
"[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}"); "[15,15,15,15]],\"altc\":[2,2,2,2],\"altd\":[2,2,2,2]}");
JsonObject& root = doc.as<JsonObject>();
SECTION("Success") { SECTION("Success") {
REQUIRE(error == JsonError::Ok); REQUIRE(error == JsonError::Ok);
} }
SECTION("ProtocolName") { SECTION("ProtocolName") {
REQUIRE("fluorescence" == _object["protocol_name"]); REQUIRE("fluorescence" == root["protocol_name"]);
} }
SECTION("Repeats") { SECTION("Repeats") {
REQUIRE(1 == _object["repeats"]); REQUIRE(1 == root["repeats"]);
} }
SECTION("Wait") { SECTION("Wait") {
REQUIRE(0 == _object["wait"]); REQUIRE(0 == root["wait"]);
} }
SECTION("Measurements") { SECTION("Measurements") {
REQUIRE(3 == _object["measurements"]); REQUIRE(3 == root["measurements"]);
} }
SECTION("Meas2_Light") { SECTION("Meas2_Light") {
REQUIRE(15 == _object["meas2_light"]); REQUIRE(15 == root["meas2_light"]);
} }
SECTION("Meas1_Baseline") { SECTION("Meas1_Baseline") {
REQUIRE(0 == _object["meas1_baseline"]); REQUIRE(0 == root["meas1_baseline"]);
} }
SECTION("Act_Light") { SECTION("Act_Light") {
REQUIRE(20 == _object["act_light"]); REQUIRE(20 == root["act_light"]);
} }
SECTION("Pulsesize") { SECTION("Pulsesize") {
REQUIRE(25 == _object["pulsesize"]); REQUIRE(25 == root["pulsesize"]);
} }
SECTION("Pulsedistance") { SECTION("Pulsedistance") {
REQUIRE(10000 == _object["pulsedistance"]); REQUIRE(10000 == root["pulsedistance"]);
} }
SECTION("Actintensity1") { SECTION("Actintensity1") {
REQUIRE(50 == _object["actintensity1"]); REQUIRE(50 == root["actintensity1"]);
} }
SECTION("Actintensity2") { SECTION("Actintensity2") {
REQUIRE(255 == _object["actintensity2"]); REQUIRE(255 == root["actintensity2"]);
} }
SECTION("Measintensity") { SECTION("Measintensity") {
REQUIRE(255 == _object["measintensity"]); REQUIRE(255 == root["measintensity"]);
} }
SECTION("Calintensity") { SECTION("Calintensity") {
REQUIRE(255 == _object["calintensity"]); REQUIRE(255 == root["calintensity"]);
} }
SECTION("Pulses") { SECTION("Pulses") {
// "pulses":[50,50,50] // "pulses":[50,50,50]
JsonArray& array = _object["pulses"]; JsonArray& array = root["pulses"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(3 == array.size()); REQUIRE(3 == array.size());
@ -93,7 +94,7 @@ TEST_CASE("Gbathree") {
SECTION("Act") { SECTION("Act") {
// "act":[2,1,2,2] // "act":[2,1,2,2]
JsonArray& array = _object["act"]; JsonArray& array = root["act"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());
@ -106,7 +107,7 @@ TEST_CASE("Gbathree") {
SECTION("Detectors") { SECTION("Detectors") {
// "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]] // "detectors":[[34,34,34,34],[34,34,34,34],[34,34,34,34],[34,34,34,34]]
JsonArray& array = _object["detectors"]; JsonArray& array = root["detectors"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());
@ -123,7 +124,7 @@ TEST_CASE("Gbathree") {
SECTION("Alta") { SECTION("Alta") {
// alta:[2,2,2,2] // alta:[2,2,2,2]
JsonArray& array = _object["alta"]; JsonArray& array = root["alta"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());
@ -136,7 +137,7 @@ TEST_CASE("Gbathree") {
SECTION("Altb") { SECTION("Altb") {
// altb:[2,2,2,2] // altb:[2,2,2,2]
JsonArray& array = _object["altb"]; JsonArray& array = root["altb"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());
@ -149,7 +150,7 @@ TEST_CASE("Gbathree") {
SECTION("Measlights") { SECTION("Measlights") {
// "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]] // "measlights":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
JsonArray& array = _object["measlights"]; JsonArray& array = root["measlights"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());
@ -167,7 +168,7 @@ TEST_CASE("Gbathree") {
SECTION("Measlights2") { SECTION("Measlights2") {
// "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]] // "measlights2":[[15,15,15,15],[15,15,15,15],[15,15,15,15],[15,15,15,15]]
JsonArray& array = _object["measlights2"]; JsonArray& array = root["measlights2"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());
@ -184,7 +185,7 @@ TEST_CASE("Gbathree") {
SECTION("Altc") { SECTION("Altc") {
// altc:[2,2,2,2] // altc:[2,2,2,2]
JsonArray& array = _object["altc"]; JsonArray& array = root["altc"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());
@ -197,7 +198,7 @@ TEST_CASE("Gbathree") {
SECTION("Altd") { SECTION("Altd") {
// altd:[2,2,2,2] // altd:[2,2,2,2]
JsonArray& array = _object["altd"]; JsonArray& array = root["altd"];
REQUIRE(array.success()); REQUIRE(array.success());
REQUIRE(4 == array.size()); REQUIRE(4 == array.size());

View File

@ -6,15 +6,15 @@
#include <catch.hpp> #include <catch.hpp>
void check(std::string originalJson) { void check(std::string originalJson) {
DynamicJsonObject obj; DynamicJsonDocument doc;
std::string prettyJson; std::string prettyJson;
deserializeJson(obj, originalJson); deserializeJson(doc, originalJson);
serializeJsonPretty(obj, prettyJson); serializeJsonPretty(doc, prettyJson);
std::string finalJson; std::string finalJson;
deserializeJson(obj, originalJson); deserializeJson(doc, originalJson);
serializeJson(obj, finalJson); serializeJson(doc, finalJson);
REQUIRE(originalJson == finalJson); REQUIRE(originalJson == finalJson);
} }

View File

@ -6,7 +6,8 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonArray::add()") { TEST_CASE("JsonArray::add()") {
DynamicJsonArray _array; DynamicJsonDocument doc;
JsonArray& _array = doc.to<JsonArray>();
SECTION("int") { SECTION("int") {
_array.add(123); _array.add(123);
@ -38,7 +39,8 @@ TEST_CASE("JsonArray::add()") {
} }
SECTION("nested array") { SECTION("nested array") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
_array.add(arr); _array.add(arr);
@ -48,7 +50,8 @@ TEST_CASE("JsonArray::add()") {
} }
SECTION("nested object") { SECTION("nested object") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
JsonObject& obj = doc2.to<JsonObject>();
_array.add(obj); _array.add(obj);
@ -59,7 +62,8 @@ TEST_CASE("JsonArray::add()") {
SECTION("array subscript") { SECTION("array subscript") {
const char* str = "hello"; const char* str = "hello";
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
arr.add(str); arr.add(str);
_array.add(arr[0]); _array.add(arr[0]);
@ -69,7 +73,8 @@ TEST_CASE("JsonArray::add()") {
SECTION("object subscript") { SECTION("object subscript") {
const char* str = "hello"; const char* str = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc2;
JsonObject& obj = doc2.to<JsonObject>();
obj["x"] = str; obj["x"] = str;
_array.add(obj["x"]); _array.add(obj["x"]);
@ -80,30 +85,30 @@ TEST_CASE("JsonArray::add()") {
SECTION("should not duplicate const char*") { SECTION("should not duplicate const char*") {
_array.add("world"); _array.add("world");
const size_t expectedSize = JSON_ARRAY_SIZE(1); const size_t expectedSize = JSON_ARRAY_SIZE(1);
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char*") { SECTION("should duplicate char*") {
_array.add(const_cast<char*>("world")); _array.add(const_cast<char*>("world"));
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate std::string") { SECTION("should duplicate std::string") {
_array.add(std::string("world")); _array.add(std::string("world"));
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should not duplicate RawJson(const char*)") { SECTION("should not duplicate RawJson(const char*)") {
_array.add(RawJson("{}")); _array.add(RawJson("{}"));
const size_t expectedSize = JSON_ARRAY_SIZE(1); const size_t expectedSize = JSON_ARRAY_SIZE(1);
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate RawJson(char*)") { SECTION("should duplicate RawJson(char*)") {
_array.add(RawJson(const_cast<char*>("{}"))); _array.add(RawJson(const_cast<char*>("{}")));
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 3; const size_t expectedSize = JSON_ARRAY_SIZE(1) + 3;
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
} }

View File

@ -6,7 +6,8 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonArray basics") { TEST_CASE("JsonArray basics") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
SECTION("SuccessIsTrue") { SECTION("SuccessIsTrue") {
REQUIRE(array.success()); REQUIRE(array.success());

View File

@ -7,7 +7,8 @@
TEST_CASE("JsonArray::copyFrom()") { TEST_CASE("JsonArray::copyFrom()") {
SECTION("OneDimension") { SECTION("OneDimension") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
char json[32]; char json[32];
int source[] = {1, 2, 3}; int source[] = {1, 2, 3};
@ -20,7 +21,8 @@ TEST_CASE("JsonArray::copyFrom()") {
SECTION("OneDimension_JsonBufferTooSmall") { SECTION("OneDimension_JsonBufferTooSmall") {
const size_t SIZE = JSON_ARRAY_SIZE(2); const size_t SIZE = JSON_ARRAY_SIZE(2);
StaticJsonArray<SIZE> array; StaticJsonDocument<SIZE> doc;
JsonArray& array = doc.to<JsonArray>();
char json[32]; char json[32];
int source[] = {1, 2, 3}; int source[] = {1, 2, 3};
@ -32,7 +34,8 @@ TEST_CASE("JsonArray::copyFrom()") {
} }
SECTION("TwoDimensions") { SECTION("TwoDimensions") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
char json[32]; char json[32];
int source[][3] = {{1, 2, 3}, {4, 5, 6}}; int source[][3] = {{1, 2, 3}, {4, 5, 6}};
@ -46,7 +49,8 @@ TEST_CASE("JsonArray::copyFrom()") {
SECTION("TwoDimensions_JsonBufferTooSmall") { SECTION("TwoDimensions_JsonBufferTooSmall") {
const size_t SIZE = const size_t SIZE =
JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2); JSON_ARRAY_SIZE(2) + JSON_ARRAY_SIZE(3) + JSON_ARRAY_SIZE(2);
StaticJsonArray<SIZE> array; StaticJsonDocument<SIZE> doc;
JsonArray& array = doc.to<JsonArray>();
char json[32]; char json[32];
int source[][3] = {{1, 2, 3}, {4, 5, 6}}; int source[][3] = {{1, 2, 3}, {4, 5, 6}};

View File

@ -6,12 +6,13 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonArray::copyTo()") { TEST_CASE("JsonArray::copyTo()") {
DynamicJsonArray array; DynamicJsonDocument doc;
SECTION("BiggerOneDimensionIntegerArray") { SECTION("BiggerOneDimensionIntegerArray") {
char json[] = "[1,2,3]"; char json[] = "[1,2,3]";
JsonError err = deserializeJson(array, json); JsonError err = deserializeJson(doc, json);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
JsonArray& array = doc.as<JsonArray>();
int destination[4] = {0}; int destination[4] = {0};
size_t result = array.copyTo(destination); size_t result = array.copyTo(destination);
@ -25,8 +26,9 @@ TEST_CASE("JsonArray::copyTo()") {
SECTION("SmallerOneDimensionIntegerArray") { SECTION("SmallerOneDimensionIntegerArray") {
char json[] = "[1,2,3]"; char json[] = "[1,2,3]";
JsonError err = deserializeJson(array, json); JsonError err = deserializeJson(doc, json);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
JsonArray& array = doc.as<JsonArray>();
int destination[2] = {0}; int destination[2] = {0};
size_t result = array.copyTo(destination); size_t result = array.copyTo(destination);
@ -39,8 +41,9 @@ TEST_CASE("JsonArray::copyTo()") {
SECTION("TwoOneDimensionIntegerArray") { SECTION("TwoOneDimensionIntegerArray") {
char json[] = "[[1,2],[3],[4]]"; char json[] = "[[1,2],[3],[4]]";
JsonError err = deserializeJson(array, json); JsonError err = deserializeJson(doc, json);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
JsonArray& array = doc.as<JsonArray>();
int destination[3][2] = {{0}}; int destination[3][2] = {{0}};
array.copyTo(destination); array.copyTo(destination);

View File

@ -7,7 +7,8 @@
template <typename TIterator> template <typename TIterator>
static void run_iterator_test() { static void run_iterator_test() {
StaticJsonArray<JSON_ARRAY_SIZE(2)> array; StaticJsonDocument<JSON_ARRAY_SIZE(2)> doc;
JsonArray& array = doc.to<JsonArray>();
array.add(12); array.add(12);
array.add(34); array.add(34);

View File

@ -6,7 +6,8 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonArray::remove()") { TEST_CASE("JsonArray::remove()") {
DynamicJsonArray _array; DynamicJsonDocument doc;
JsonArray& _array = doc.to<JsonArray>();
_array.add(1); _array.add(1);
_array.add(2); _array.add(2);
_array.add(3); _array.add(3);

View File

@ -8,7 +8,8 @@
using namespace Catch::Matchers; using namespace Catch::Matchers;
TEST_CASE("JsonArray::set()") { TEST_CASE("JsonArray::set()") {
DynamicJsonArray _array; DynamicJsonDocument doc;
JsonArray& _array = doc.to<JsonArray>();
_array.add(0); _array.add(0);
SECTION("int") { SECTION("int") {
@ -40,7 +41,8 @@ TEST_CASE("JsonArray::set()") {
} }
SECTION("nested array") { SECTION("nested array") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
_array.set(0, arr); _array.set(0, arr);
@ -50,7 +52,8 @@ TEST_CASE("JsonArray::set()") {
} }
SECTION("nested object") { SECTION("nested object") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
JsonObject& obj = doc2.to<JsonObject>();
_array.set(0, obj); _array.set(0, obj);
@ -60,7 +63,8 @@ TEST_CASE("JsonArray::set()") {
} }
SECTION("array subscript") { SECTION("array subscript") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
arr.add("hello"); arr.add("hello");
_array.set(0, arr[0]); _array.set(0, arr[0]);
@ -69,7 +73,8 @@ TEST_CASE("JsonArray::set()") {
} }
SECTION("object subscript") { SECTION("object subscript") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
JsonObject& obj = doc2.to<JsonObject>();
obj["x"] = "hello"; obj["x"] = "hello";
_array.set(0, obj["x"]); _array.set(0, obj["x"]);
@ -80,18 +85,18 @@ TEST_CASE("JsonArray::set()") {
SECTION("should not duplicate const char*") { SECTION("should not duplicate const char*") {
_array.set(0, "world"); _array.set(0, "world");
const size_t expectedSize = JSON_ARRAY_SIZE(1); const size_t expectedSize = JSON_ARRAY_SIZE(1);
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char*") { SECTION("should duplicate char*") {
_array.set(0, const_cast<char*>("world")); _array.set(0, const_cast<char*>("world"));
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate std::string") { SECTION("should duplicate std::string") {
_array.set(0, std::string("world")); _array.set(0, std::string("world"));
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
} }

View File

@ -6,7 +6,8 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonArray::size()") { TEST_CASE("JsonArray::size()") {
DynamicJsonArray _array; DynamicJsonDocument doc;
JsonArray& _array = doc.to<JsonArray>();
SECTION("increases after add()") { SECTION("increases after add()") {
_array.add("hello"); _array.add("hello");

View File

@ -7,7 +7,8 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonArray::operator[]") { TEST_CASE("JsonArray::operator[]") {
DynamicJsonArray _array; DynamicJsonDocument doc;
JsonArray& _array = doc.to<JsonArray>();
_array.add(0); _array.add(0);
SECTION("int") { SECTION("int") {
@ -51,7 +52,8 @@ TEST_CASE("JsonArray::operator[]") {
} }
SECTION("nested array") { SECTION("nested array") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
_array[0] = arr; _array[0] = arr;
@ -64,7 +66,8 @@ TEST_CASE("JsonArray::operator[]") {
} }
SECTION("nested object") { SECTION("nested object") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
JsonObject& obj = doc2.to<JsonObject>();
_array[0] = obj; _array[0] = obj;
@ -77,7 +80,8 @@ TEST_CASE("JsonArray::operator[]") {
} }
SECTION("array subscript") { SECTION("array subscript") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
const char* str = "hello"; const char* str = "hello";
arr.add(str); arr.add(str);
@ -88,8 +92,9 @@ TEST_CASE("JsonArray::operator[]") {
} }
SECTION("object subscript") { SECTION("object subscript") {
DynamicJsonObject obj;
const char* str = "hello"; const char* str = "hello";
DynamicJsonDocument doc2;
JsonObject& obj = doc2.to<JsonObject>();
obj["x"] = str; obj["x"] = str;
@ -101,18 +106,18 @@ TEST_CASE("JsonArray::operator[]") {
SECTION("should not duplicate const char*") { SECTION("should not duplicate const char*") {
_array[0] = "world"; _array[0] = "world";
const size_t expectedSize = JSON_ARRAY_SIZE(1); const size_t expectedSize = JSON_ARRAY_SIZE(1);
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char*") { SECTION("should duplicate char*") {
_array[0] = const_cast<char*>("world"); _array[0] = const_cast<char*>("world");
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate std::string") { SECTION("should duplicate std::string") {
_array[0] = std::string("world"); _array[0] = std::string("world");
const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6; const size_t expectedSize = JSON_ARRAY_SIZE(1) + 6;
REQUIRE(expectedSize == _array.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
} }

View File

@ -0,0 +1,16 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# MIT License
add_executable(JsonDeserializerTests
deserializeJsonArray.cpp
deserializeJsonArrayStatic.cpp
deserializeJsonObject.cpp
deserializeJsonObjectStatic.cpp
deserializeJsonValue.cpp
JsonError.cpp
nestingLimit.cpp
)
target_link_libraries(JsonDeserializerTests catch)
add_test(JsonDeserializer JsonDeserializerTests)

View File

@ -22,23 +22,21 @@ void testBoolification(JsonError error, bool expected) {
TEST_CASE("JsonError") { TEST_CASE("JsonError") {
SECTION("c_str()") { SECTION("c_str()") {
TEST_STRINGIFICATION(Ok); TEST_STRINGIFICATION(Ok);
TEST_STRINGIFICATION(OpeningBraceExpected);
TEST_STRINGIFICATION(ClosingBraceExpected);
TEST_STRINGIFICATION(OpeningBracketExpected);
TEST_STRINGIFICATION(ClosingBracketExpected);
TEST_STRINGIFICATION(ColonExpected);
TEST_STRINGIFICATION(TooDeep); TEST_STRINGIFICATION(TooDeep);
TEST_STRINGIFICATION(NoMemory); TEST_STRINGIFICATION(NoMemory);
TEST_STRINGIFICATION(InvalidInput);
} }
SECTION("as boolean") { SECTION("as boolean") {
TEST_BOOLIFICATION(Ok, false); TEST_BOOLIFICATION(Ok, false);
TEST_BOOLIFICATION(OpeningBraceExpected, true);
TEST_BOOLIFICATION(ClosingBraceExpected, true);
TEST_BOOLIFICATION(OpeningBracketExpected, true);
TEST_BOOLIFICATION(ClosingBracketExpected, true);
TEST_BOOLIFICATION(ColonExpected, true);
TEST_BOOLIFICATION(TooDeep, true); TEST_BOOLIFICATION(TooDeep, true);
TEST_BOOLIFICATION(NoMemory, true); TEST_BOOLIFICATION(NoMemory, true);
TEST_BOOLIFICATION(InvalidInput, true);
}
SECTION("ostream") {
std::stringstream s;
s << JsonError::InvalidInput;
REQUIRE(s.str() == "InvalidInput");
} }
} }

View File

@ -5,11 +5,12 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("deserializeJson(DynamicJsonArray&)") { TEST_CASE("deserialize JSON array") {
DynamicJsonArray arr; DynamicJsonDocument doc;
SECTION("An empty array") { SECTION("An empty array") {
JsonError err = deserializeJson(arr, "[]"); JsonError err = deserializeJson(doc, "[]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(0 == arr.size()); REQUIRE(0 == arr.size());
@ -17,14 +18,16 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
SECTION("Spaces") { SECTION("Spaces") {
SECTION("Before the opening bracket") { SECTION("Before the opening bracket") {
JsonError err = deserializeJson(arr, " []"); JsonError err = deserializeJson(doc, " []");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(0 == arr.size()); REQUIRE(0 == arr.size());
} }
SECTION("Before first value") { SECTION("Before first value") {
JsonError err = deserializeJson(arr, "[ \t\r\n42]"); JsonError err = deserializeJson(doc, "[ \t\r\n42]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -32,7 +35,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("After first value") { SECTION("After first value") {
JsonError err = deserializeJson(arr, "[42 \t\r\n]"); JsonError err = deserializeJson(doc, "[42 \t\r\n]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -42,7 +46,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
SECTION("Values types") { SECTION("Values types") {
SECTION("On integer") { SECTION("On integer") {
JsonError err = deserializeJson(arr, "[42]"); JsonError err = deserializeJson(doc, "[42]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -50,7 +55,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Two integers") { SECTION("Two integers") {
JsonError err = deserializeJson(arr, "[42,84]"); JsonError err = deserializeJson(doc, "[42,84]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -59,7 +65,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Double") { SECTION("Double") {
JsonError err = deserializeJson(arr, "[4.2,1e2]"); JsonError err = deserializeJson(doc, "[4.2,1e2]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -68,7 +75,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Unsigned long") { SECTION("Unsigned long") {
JsonError err = deserializeJson(arr, "[4294967295]"); JsonError err = deserializeJson(doc, "[4294967295]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -76,7 +84,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Boolean") { SECTION("Boolean") {
JsonError err = deserializeJson(arr, "[true,false]"); JsonError err = deserializeJson(doc, "[true,false]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -85,18 +94,20 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Null") { SECTION("Null") {
JsonError err = deserializeJson(arr, "[null,null]"); JsonError err = deserializeJson(doc, "[null,null]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
REQUIRE(arr[0].as<char *>() == 0); REQUIRE(arr[0].as<char*>() == 0);
REQUIRE(arr[1].as<char *>() == 0); REQUIRE(arr[1].as<char*>() == 0);
} }
} }
SECTION("Quotes") { SECTION("Quotes") {
SECTION("Double quotes") { SECTION("Double quotes") {
JsonError err = deserializeJson(arr, "[ \"hello\" , \"world\" ]"); JsonError err = deserializeJson(doc, "[ \"hello\" , \"world\" ]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -105,7 +116,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Single quotes") { SECTION("Single quotes") {
JsonError err = deserializeJson(arr, "[ 'hello' , 'world' ]"); JsonError err = deserializeJson(doc, "[ 'hello' , 'world' ]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -114,7 +126,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("No quotes") { SECTION("No quotes") {
JsonError err = deserializeJson(arr, "[ hello , world ]"); JsonError err = deserializeJson(doc, "[ hello , world ]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -123,7 +136,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Double quotes (empty strings)") { SECTION("Double quotes (empty strings)") {
JsonError err = deserializeJson(arr, "[\"\",\"\"]"); JsonError err = deserializeJson(doc, "[\"\",\"\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -132,7 +146,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Single quotes (empty strings)") { SECTION("Single quotes (empty strings)") {
JsonError err = deserializeJson(arr, "[\'\',\'\']"); JsonError err = deserializeJson(doc, "[\'\',\'\']");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -141,30 +156,28 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("No quotes (empty strings)") { SECTION("No quotes (empty strings)") {
JsonError err = deserializeJson(arr, "[,]"); JsonError err = deserializeJson(doc, "[,]");
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
REQUIRE(2 == arr.size());
REQUIRE(arr[0] == "");
REQUIRE(arr[1] == "");
} }
SECTION("Closing single quotes missing") { SECTION("Closing single quotes missing") {
JsonError err = deserializeJson(arr, "[\"]"); JsonError err = deserializeJson(doc, "[\"]");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("Closing double quotes missing") { SECTION("Closing double quotes missing") {
JsonError err = deserializeJson(arr, "[\']"); JsonError err = deserializeJson(doc, "[\']");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
} }
SECTION("Block comments") { SECTION("Block comments") {
SECTION("Before opening bracket") { SECTION("Before opening bracket") {
JsonError err = deserializeJson(arr, "/*COMMENT*/ [\"hello\"]"); JsonError err = deserializeJson(doc, "/*COMMENT*/ [\"hello\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -172,7 +185,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("After opening bracket") { SECTION("After opening bracket") {
JsonError err = deserializeJson(arr, "[/*COMMENT*/ \"hello\"]"); JsonError err = deserializeJson(doc, "[/*COMMENT*/ \"hello\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -180,7 +194,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Before closing bracket") { SECTION("Before closing bracket") {
JsonError err = deserializeJson(arr, "[\"hello\"/*COMMENT*/]"); JsonError err = deserializeJson(doc, "[\"hello\"/*COMMENT*/]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -188,7 +203,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("After closing bracket") { SECTION("After closing bracket") {
JsonError err = deserializeJson(arr, "[\"hello\"]/*COMMENT*/"); JsonError err = deserializeJson(doc, "[\"hello\"]/*COMMENT*/");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -196,7 +212,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Before comma") { SECTION("Before comma") {
JsonError err = deserializeJson(arr, "[\"hello\"/*COMMENT*/,\"world\"]"); JsonError err = deserializeJson(doc, "[\"hello\"/*COMMENT*/,\"world\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -205,7 +222,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("After comma") { SECTION("After comma") {
JsonError err = deserializeJson(arr, "[\"hello\",/*COMMENT*/ \"world\"]"); JsonError err = deserializeJson(doc, "[\"hello\",/*COMMENT*/ \"world\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -214,24 +232,25 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("/*/") { SECTION("/*/") {
JsonError err = deserializeJson(arr, "[/*/\n]"); JsonError err = deserializeJson(doc, "[/*/\n]");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("Unfinished comment") { SECTION("Unfinished comment") {
JsonError err = deserializeJson(arr, "[/*COMMENT]"); JsonError err = deserializeJson(doc, "[/*COMMENT]");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("Final slash missing") { SECTION("Final slash missing") {
JsonError err = deserializeJson(arr, "[/*COMMENT*]"); JsonError err = deserializeJson(doc, "[/*COMMENT*]");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
} }
SECTION("Line comments") { SECTION("Line comments") {
SECTION("Before opening bracket") { SECTION("Before opening bracket") {
JsonError err = deserializeJson(arr, "//COMMENT\n\t[\"hello\"]"); JsonError err = deserializeJson(doc, "//COMMENT\n\t[\"hello\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -239,7 +258,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("After opening bracket") { SECTION("After opening bracket") {
JsonError err = deserializeJson(arr, "[//COMMENT\n\"hello\"]"); JsonError err = deserializeJson(doc, "[//COMMENT\n\"hello\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -247,7 +267,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Before closing bracket") { SECTION("Before closing bracket") {
JsonError err = deserializeJson(arr, "[\"hello\"//COMMENT\r\n]"); JsonError err = deserializeJson(doc, "[\"hello\"//COMMENT\r\n]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -255,7 +276,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("After closing bracket") { SECTION("After closing bracket") {
JsonError err = deserializeJson(arr, "[\"hello\"]//COMMENT\n"); JsonError err = deserializeJson(doc, "[\"hello\"]//COMMENT\n");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -263,7 +285,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Before comma") { SECTION("Before comma") {
JsonError err = deserializeJson(arr, "[\"hello\"//COMMENT\n,\"world\"]"); JsonError err = deserializeJson(doc, "[\"hello\"//COMMENT\n,\"world\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -272,7 +295,8 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("After comma") { SECTION("After comma") {
JsonError err = deserializeJson(arr, "[\"hello\",//COMMENT\n\"world\"]"); JsonError err = deserializeJson(doc, "[\"hello\",//COMMENT\n\"world\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(2 == arr.size()); REQUIRE(2 == arr.size());
@ -281,57 +305,55 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Invalid comment") { SECTION("Invalid comment") {
JsonError err = deserializeJson(arr, "[/COMMENT\n]"); JsonError err = deserializeJson(doc, "[/COMMENT\n]");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("End document with comment") { SECTION("End document with comment") {
JsonError err = deserializeJson(arr, "[//COMMENT"); JsonError err = deserializeJson(doc, "[//COMMENT");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
} }
SECTION("Misc") { SECTION("Misc") {
SECTION("Garbage") { SECTION("Garbage") {
JsonError err = deserializeJson(arr, "%*$£¤"); JsonError err = deserializeJson(doc, "%*$£¤");
REQUIRE(err != JsonError::Ok); REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("The opening bracket is missing") { SECTION("The opening bracket is missing") {
JsonError err = deserializeJson(arr, "]"); JsonError err = deserializeJson(doc, "]");
REQUIRE(err != JsonError::Ok); // TODO REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("The closing bracket is missing") { SECTION("The closing bracket is missing") {
JsonError err = deserializeJson(arr, "["); JsonError err = deserializeJson(doc, "[");
REQUIRE(err != JsonError::Ok); // TODO
REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("Escape sequences") { SECTION("Escape sequences") {
JsonError err = JsonError err =
deserializeJson(arr, "[\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"]"); deserializeJson(doc, "[\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
REQUIRE(arr[0] == "1\"2\\3/4\b5\f6\n7\r8\t9"); REQUIRE(arr[0] == "1\"2\\3/4\b5\f6\n7\r8\t9");
} }
SECTION("Unterminated escape sequence") {
JsonError err = deserializeJson(arr, "\"\\\0\"", 4);
REQUIRE(err != JsonError::Ok);
}
SECTION("Nested objects") { SECTION("Nested objects") {
char jsonString[] = char jsonString[] =
" [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] "; " [ { \"a\" : 1 , \"b\" : 2 } , { \"c\" : 3 , \"d\" : 4 } ] ";
JsonError err = deserializeJson(arr, jsonString); JsonError err = deserializeJson(doc, jsonString);
JsonArray& arr = doc.as<JsonArray>();
JsonObject &object1 = arr[0]; JsonObject& object1 = arr[0];
const JsonObject &object2 = arr[1]; const JsonObject& object2 = arr[1];
JsonObject &object3 = arr[2]; JsonObject& object3 = arr[2];
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
@ -352,10 +374,11 @@ TEST_CASE("deserializeJson(DynamicJsonArray&)") {
} }
SECTION("Should clear the JsonArray") { SECTION("Should clear the JsonArray") {
deserializeJson(arr, "[1,2,3,4]"); deserializeJson(doc, "[1,2,3,4]");
deserializeJson(arr, "[]"); deserializeJson(doc, "[]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(arr.size() == 0); REQUIRE(arr.size() == 0);
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(0)); REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
} }
} }

View File

@ -0,0 +1,105 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("deserialize JSON array with a StaticJsonDocument") {
SECTION("BufferOfTheRightSizeForEmptyArray") {
StaticJsonDocument<JSON_ARRAY_SIZE(0)> doc;
char input[] = "[]";
JsonError err = deserializeJson(doc, input);
REQUIRE(err == JsonError::Ok);
}
SECTION("TooSmallBufferForArrayWithOneValue") {
StaticJsonDocument<JSON_ARRAY_SIZE(1) - 1> doc;
char input[] = "[1]";
JsonError err = deserializeJson(doc, input);
REQUIRE(err != JsonError::Ok);
}
SECTION("BufferOfTheRightSizeForArrayWithOneValue") {
StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
char input[] = "[1]";
JsonError err = deserializeJson(doc, input);
REQUIRE(err == JsonError::Ok);
}
SECTION("TooSmallBufferForArrayWithNestedObject") {
StaticJsonDocument<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0) - 1> doc;
char input[] = "[{}]";
JsonError err = deserializeJson(doc, input);
REQUIRE(err != JsonError::Ok);
}
SECTION("BufferOfTheRightSizeForArrayWithNestedObject") {
StaticJsonDocument<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0)> doc;
char input[] = "[{}]";
JsonError err = deserializeJson(doc, input);
REQUIRE(err == JsonError::Ok);
}
SECTION("CharPtrNull") {
StaticJsonDocument<100> doc;
JsonError err = deserializeJson(doc, static_cast<char*>(0));
REQUIRE(err != JsonError::Ok);
}
SECTION("ConstCharPtrNull") {
StaticJsonDocument<100> doc;
JsonError err = deserializeJson(doc, static_cast<const char*>(0));
REQUIRE(err != JsonError::Ok);
}
SECTION("CopyStringNotSpaces") {
StaticJsonDocument<100> doc;
deserializeJson(doc, " [ \"1234567\" ] ");
REQUIRE(JSON_ARRAY_SIZE(1) + sizeof("1234567") == doc.memoryUsage());
// note: we use a string of 8 bytes to be sure that the StaticJsonBuffer
// will not insert bytes to enforce alignement
}
SECTION("Should clear the JsonArray") {
StaticJsonDocument<JSON_ARRAY_SIZE(4)> doc;
char input[] = "[1,2,3,4]";
deserializeJson(doc, input);
deserializeJson(doc, "[]");
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(arr.size() == 0);
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(0));
}
SECTION("Array") {
StaticJsonDocument<JSON_ARRAY_SIZE(2)> doc;
char input[] = "[1,2]";
JsonError err = deserializeJson(doc, input);
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonArray>());
REQUIRE(doc.memoryUsage() == JSON_ARRAY_SIZE(2));
REQUIRE(arr[0] == 1);
REQUIRE(arr[1] == 2);
}
}

View File

@ -5,40 +5,55 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("deserializeJson(DynamicJsonObject&)") { TEST_CASE("deserialize JSON object") {
DynamicJsonObject obj; DynamicJsonDocument doc;
SECTION("An empty object") { SECTION("An empty object") {
JsonError err = deserializeJson(obj, "{}"); JsonError err = deserializeJson(doc, "{}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 0); REQUIRE(obj.size() == 0);
} }
SECTION("Quotes") { SECTION("Quotes") {
SECTION("Double quotes") { SECTION("Double quotes") {
JsonError err = deserializeJson(obj, "{\"key\":\"value\"}"); JsonError err = deserializeJson(doc, "{\"key\":\"value\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["key"] == "value"); REQUIRE(obj["key"] == "value");
} }
SECTION("Single quotes") { SECTION("Single quotes") {
JsonError err = deserializeJson(obj, "{'key':'value'}"); JsonError err = deserializeJson(doc, "{'key':'value'}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["key"] == "value"); REQUIRE(obj["key"] == "value");
} }
SECTION("No quotes") { SECTION("No quotes") {
JsonError err = deserializeJson(obj, "{key:value}"); JsonError err = deserializeJson(doc, "{key:value}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["key"] == "value"); REQUIRE(obj["key"] == "value");
} }
SECTION("No quotes, allow underscore in key") { SECTION("No quotes, allow underscore in key") {
JsonError err = deserializeJson(obj, "{_k_e_y_:42}"); JsonError err = deserializeJson(doc, "{_k_e_y_:42}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["_k_e_y_"] == 42); REQUIRE(obj["_k_e_y_"] == 42);
} }
@ -46,37 +61,52 @@ TEST_CASE("deserializeJson(DynamicJsonObject&)") {
SECTION("Spaces") { SECTION("Spaces") {
SECTION("Before the key") { SECTION("Before the key") {
JsonError err = deserializeJson(obj, "{ \"key\":\"value\"}"); JsonError err = deserializeJson(doc, "{ \"key\":\"value\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["key"] == "value"); REQUIRE(obj["key"] == "value");
} }
SECTION("After the key") { SECTION("After the key") {
JsonError err = deserializeJson(obj, "{\"key\" :\"value\"}"); JsonError err = deserializeJson(doc, "{\"key\" :\"value\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["key"] == "value"); REQUIRE(obj["key"] == "value");
} }
SECTION("Before the value") { SECTION("Before the value") {
JsonError err = deserializeJson(obj, "{\"key\": \"value\"}"); JsonError err = deserializeJson(doc, "{\"key\": \"value\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["key"] == "value"); REQUIRE(obj["key"] == "value");
} }
SECTION("After the value") { SECTION("After the value") {
JsonError err = deserializeJson(obj, "{\"key\":\"value\" }"); JsonError err = deserializeJson(doc, "{\"key\":\"value\" }");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 1); REQUIRE(obj.size() == 1);
REQUIRE(obj["key"] == "value"); REQUIRE(obj["key"] == "value");
} }
SECTION("Before the colon") { SECTION("Before the colon") {
JsonError err = JsonError err =
deserializeJson(obj, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); deserializeJson(doc, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 2); REQUIRE(obj.size() == 2);
REQUIRE(obj["key1"] == "value1"); REQUIRE(obj["key1"] == "value1");
REQUIRE(obj["key2"] == "value2"); REQUIRE(obj["key2"] == "value2");
@ -84,8 +114,11 @@ TEST_CASE("deserializeJson(DynamicJsonObject&)") {
SECTION("After the colon") { SECTION("After the colon") {
JsonError err = JsonError err =
deserializeJson(obj, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}"); deserializeJson(doc, "{\"key1\":\"value1\" ,\"key2\":\"value2\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 2); REQUIRE(obj.size() == 2);
REQUIRE(obj["key1"] == "value1"); REQUIRE(obj["key1"] == "value1");
REQUIRE(obj["key2"] == "value2"); REQUIRE(obj["key2"] == "value2");
@ -95,53 +128,69 @@ TEST_CASE("deserializeJson(DynamicJsonObject&)") {
SECTION("Values types") { SECTION("Values types") {
SECTION("String") { SECTION("String") {
JsonError err = JsonError err =
deserializeJson(obj, "{\"key1\":\"value1\",\"key2\":\"value2\"}"); deserializeJson(doc, "{\"key1\":\"value1\",\"key2\":\"value2\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 2); REQUIRE(obj.size() == 2);
REQUIRE(obj["key1"] == "value1"); REQUIRE(obj["key1"] == "value1");
REQUIRE(obj["key2"] == "value2"); REQUIRE(obj["key2"] == "value2");
} }
SECTION("Integer") { SECTION("Integer") {
JsonError err = deserializeJson(obj, "{\"key1\":42,\"key2\":-42}"); JsonError err = deserializeJson(doc, "{\"key1\":42,\"key2\":-42}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 2); REQUIRE(obj.size() == 2);
REQUIRE(obj["key1"] == 42); REQUIRE(obj["key1"] == 42);
REQUIRE(obj["key2"] == -42); REQUIRE(obj["key2"] == -42);
} }
SECTION("Double") { SECTION("Double") {
JsonError err = deserializeJson(obj, "{\"key1\":12.345,\"key2\":-7E89}"); JsonError err = deserializeJson(doc, "{\"key1\":12.345,\"key2\":-7E89}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 2); REQUIRE(obj.size() == 2);
REQUIRE(obj["key1"] == 12.345); REQUIRE(obj["key1"] == 12.345);
REQUIRE(obj["key2"] == -7E89); REQUIRE(obj["key2"] == -7E89);
} }
SECTION("Booleans") { SECTION("Booleans") {
JsonError err = deserializeJson(obj, "{\"key1\":true,\"key2\":false}"); JsonError err = deserializeJson(doc, "{\"key1\":true,\"key2\":false}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 2); REQUIRE(obj.size() == 2);
REQUIRE(obj["key1"] == true); REQUIRE(obj["key1"] == true);
REQUIRE(obj["key2"] == false); REQUIRE(obj["key2"] == false);
} }
SECTION("Null") { SECTION("Null") {
JsonError err = deserializeJson(obj, "{\"key1\":null,\"key2\":null}"); JsonError err = deserializeJson(doc, "{\"key1\":null,\"key2\":null}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 2); REQUIRE(obj.size() == 2);
REQUIRE(obj["key1"].as<char *>() == 0); REQUIRE(obj["key1"].as<char*>() == 0);
REQUIRE(obj["key2"].as<char *>() == 0); REQUIRE(obj["key2"].as<char*>() == 0);
} }
SECTION("Array") { SECTION("Array") {
char jsonString[] = " { \"ab\" : [ 1 , 2 ] , \"cd\" : [ 3 , 4 ] } "; char jsonString[] = " { \"ab\" : [ 1 , 2 ] , \"cd\" : [ 3 , 4 ] } ";
JsonError err = deserializeJson(obj, jsonString); JsonError err = deserializeJson(doc, jsonString);
JsonObject& obj = doc.as<JsonObject>();
JsonArray &array1 = obj["ab"]; JsonArray& array1 = obj["ab"];
const JsonArray &array2 = obj["cd"]; const JsonArray& array2 = obj["cd"];
JsonArray &array3 = obj["ef"]; JsonArray& array3 = obj["ef"];
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
@ -165,40 +214,49 @@ TEST_CASE("deserializeJson(DynamicJsonObject&)") {
SECTION("Misc") { SECTION("Misc") {
SECTION("The opening brace is missing") { SECTION("The opening brace is missing") {
JsonError err = deserializeJson(obj, "}"); JsonError err = deserializeJson(doc, "}");
REQUIRE(err == JsonError::OpeningBraceExpected);
REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("The closing brace is missing") { SECTION("The closing brace is missing") {
JsonError err = deserializeJson(obj, "{\"hello\":\"world\""); JsonError err = deserializeJson(doc, "{\"hello\":\"world\"");
REQUIRE(err == JsonError::ClosingBraceExpected);
REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("A quoted key without value") { SECTION("A quoted key without value") {
JsonError err = deserializeJson(obj, "{\"key\"}"); JsonError err = deserializeJson(doc, "{\"key\"}");
REQUIRE(err == JsonError::ColonExpected);
REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("A non-quoted key without value") { SECTION("A non-quoted key without value") {
JsonError err = deserializeJson(obj, "{key}"); JsonError err = deserializeJson(doc, "{key}");
REQUIRE(err == JsonError::ColonExpected);
REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("A dangling comma") { SECTION("A dangling comma") {
JsonError err = deserializeJson(obj, "{\"key1\":\"value1\",}"); JsonError err = deserializeJson(doc, "{\"key1\":\"value1\",}");
REQUIRE(err == JsonError::ColonExpected);
REQUIRE(err == JsonError::InvalidInput);
} }
SECTION("null as a key") { SECTION("null as a key") {
JsonError err = deserializeJson(obj, "{null:\"value\"}"); JsonError err = deserializeJson(doc, "{null:\"value\"}");
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
} }
} }
SECTION("Should clear the JsonObject") { SECTION("Should clear the JsonObject") {
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
deserializeJson(obj, "{}"); deserializeJson(doc, "{}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 0); REQUIRE(obj.size() == 0);
REQUIRE(obj.memoryUsage() == JSON_OBJECT_SIZE(0)); REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
} }
} }

View File

@ -5,76 +5,76 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("deserializeJson(StaticJsonObject&)") { TEST_CASE("deserialize JSON object with StaticJsonDocument") {
SECTION("BufferOfTheRightSizeForEmptyObject") { SECTION("BufferOfTheRightSizeForEmptyObject") {
StaticJsonObject<JSON_OBJECT_SIZE(0)> obj; StaticJsonDocument<JSON_OBJECT_SIZE(0)> doc;
char input[] = "{}"; char input[] = "{}";
JsonError err = deserializeJson(obj, input); JsonError err = deserializeJson(doc, input);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
} }
SECTION("TooSmallBufferForObjectWithOneValue") { SECTION("TooSmallBufferForObjectWithOneValue") {
StaticJsonObject<JSON_OBJECT_SIZE(1) - 1> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1) - 1> doc;
char input[] = "{\"a\":1}"; char input[] = "{\"a\":1}";
JsonError err = deserializeJson(obj, input); JsonError err = deserializeJson(doc, input);
REQUIRE(err != JsonError::Ok); REQUIRE(err != JsonError::Ok);
} }
SECTION("BufferOfTheRightSizeForObjectWithOneValue") { SECTION("BufferOfTheRightSizeForObjectWithOneValue") {
StaticJsonObject<JSON_OBJECT_SIZE(1)> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
char input[] = "{\"a\":1}"; char input[] = "{\"a\":1}";
JsonError err = deserializeJson(obj, input); JsonError err = deserializeJson(doc, input);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
} }
SECTION("TooSmallBufferForObjectWithNestedObject") { SECTION("TooSmallBufferForObjectWithNestedObject") {
StaticJsonObject<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0) - 1> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0) - 1> doc;
char input[] = "{\"a\":[]}"; char input[] = "{\"a\":[]}";
JsonError err = deserializeJson(obj, input); JsonError err = deserializeJson(doc, input);
REQUIRE(err != JsonError::Ok); REQUIRE(err != JsonError::Ok);
} }
SECTION("BufferOfTheRightSizeForObjectWithNestedObject") { SECTION("BufferOfTheRightSizeForObjectWithNestedObject") {
StaticJsonObject<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0)> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1) + JSON_ARRAY_SIZE(0)> doc;
char input[] = "{\"a\":[]}"; char input[] = "{\"a\":[]}";
JsonError err = deserializeJson(obj, input); JsonError err = deserializeJson(doc, input);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
} }
SECTION("CharPtrNull") { SECTION("CharPtrNull") {
StaticJsonObject<100> obj; StaticJsonDocument<100> doc;
JsonError err = deserializeJson(obj, static_cast<char*>(0)); JsonError err = deserializeJson(doc, static_cast<char*>(0));
REQUIRE(err != JsonError::Ok); REQUIRE(err != JsonError::Ok);
} }
SECTION("ConstCharPtrNull") { SECTION("ConstCharPtrNull") {
StaticJsonObject<100> obj; StaticJsonDocument<100> doc;
JsonError err = deserializeJson(obj, static_cast<const char*>(0)); JsonError err = deserializeJson(doc, static_cast<const char*>(0));
REQUIRE(err != JsonError::Ok); REQUIRE(err != JsonError::Ok);
} }
SECTION("Should clear the JsonObject") { SECTION("Should clear the JsonObject") {
StaticJsonObject<JSON_OBJECT_SIZE(1)> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
char input[] = "{\"hello\":\"world\"}"; char input[] = "{\"hello\":\"world\"}";
deserializeJson(obj, input); deserializeJson(doc, input);
deserializeJson(obj, "{}"); deserializeJson(doc, "{}");
REQUIRE(obj.size() == 0); REQUIRE(doc.as<JsonObject>().size() == 0);
REQUIRE(obj.memoryUsage() == JSON_OBJECT_SIZE(0)); REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
} }
} }

View File

@ -0,0 +1,103 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
using namespace Catch::Matchers;
TEST_CASE("deserializeJson(DynamicJsonDocument&)") {
DynamicJsonDocument doc;
SECTION("EmptyObject") {
JsonError err = deserializeJson(doc, "{}");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonObject>());
}
SECTION("EmptyArray") {
JsonError err = deserializeJson(doc, "[]");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<JsonArray>());
}
SECTION("Integer") {
JsonError err = deserializeJson(doc, "-42");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<int>());
REQUIRE_FALSE(doc.is<bool>());
REQUIRE(doc.as<int>() == -42);
}
SECTION("Double") {
JsonError err = deserializeJson(doc, "-1.23e+4");
REQUIRE(err == JsonError::Ok);
REQUIRE_FALSE(doc.is<int>());
REQUIRE(doc.is<double>());
REQUIRE(doc.as<double>() == Approx(-1.23e+4));
}
SECTION("Double quoted string") {
JsonError err = deserializeJson(doc, "\"hello world\"");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<char*>());
REQUIRE_THAT(doc.as<char*>(), Equals("hello world"));
}
SECTION("Single quoted string") {
JsonError err = deserializeJson(doc, "\'hello world\'");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<char*>());
REQUIRE_THAT(doc.as<char*>(), Equals("hello world"));
}
SECTION("True") {
JsonError err = deserializeJson(doc, "true");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<bool>());
REQUIRE(doc.as<bool>() == true);
}
SECTION("False") {
JsonError err = deserializeJson(doc, "false");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<bool>());
REQUIRE(doc.as<bool>() == false);
}
SECTION("OpenBrace") {
JsonError err = deserializeJson(doc, "{");
REQUIRE(err != JsonError::Ok);
}
SECTION("Incomplete string") {
JsonError err = deserializeJson(doc, "\"hello");
REQUIRE(err == JsonError::Ok);
REQUIRE(doc.is<char*>());
REQUIRE_THAT(doc.as<char*>(), Equals("hello"));
}
SECTION("Unterminated escape sequence") {
JsonError err = deserializeJson(doc, "\"\\\0\"");
REQUIRE(err == JsonError::InvalidInput);
}
SECTION("Should clear the JsonVariant") {
deserializeJson(doc, "[1,2,3]");
deserializeJson(doc, "{}");
REQUIRE(doc.is<JsonObject>());
REQUIRE(doc.memoryUsage() == JSON_OBJECT_SIZE(0));
}
}

View File

@ -0,0 +1,32 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#define SHOULD_WORK(expression) REQUIRE(JsonError::Ok == expression);
#define SHOULD_FAIL(expression) REQUIRE(JsonError::TooDeep == expression);
TEST_CASE("JsonDeserializer nestingLimit") {
DynamicJsonDocument doc;
SECTION("limit = 0") {
SHOULD_WORK(deserializeJson(doc, "\"toto\"", 0));
SHOULD_WORK(deserializeJson(doc, "123", 0));
SHOULD_WORK(deserializeJson(doc, "true", 0));
SHOULD_FAIL(deserializeJson(doc, "[]", 0));
SHOULD_FAIL(deserializeJson(doc, "{}", 0));
SHOULD_FAIL(deserializeJson(doc, "[\"toto\"]", 0));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":1}", 0));
}
SECTION("limit = 1") {
SHOULD_WORK(deserializeJson(doc, "[\"toto\"]", 1));
SHOULD_WORK(deserializeJson(doc, "{\"toto\":1}", 1));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":{}}", 1));
SHOULD_FAIL(deserializeJson(doc, "{\"toto\":[]}", 1));
SHOULD_FAIL(deserializeJson(doc, "[[\"toto\"]]", 1));
SHOULD_FAIL(deserializeJson(doc, "[{\"toto\":1}]", 1));
}
}

View File

@ -6,13 +6,10 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonObject basics") { TEST_CASE("JsonObject basics") {
DynamicJsonObject _object; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
SECTION("InitialSizeIsZero") {
REQUIRE(0 == _object.size());
}
SECTION("SuccessIsTrue") { SECTION("SuccessIsTrue") {
REQUIRE(_object.success()); REQUIRE(obj.success());
} }
} }

View File

@ -6,24 +6,25 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonObject::containsKey()") { TEST_CASE("JsonObject::containsKey()") {
DynamicJsonObject _object; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
SECTION("ContainsKeyReturnsFalseForNonExistingKey") { SECTION("ContainsKeyReturnsFalseForNonExistingKey") {
_object.set("hello", 42); obj.set("hello", 42);
REQUIRE(false == _object.containsKey("world")); REQUIRE(false == obj.containsKey("world"));
} }
SECTION("ContainsKeyReturnsTrueForDefinedValue") { SECTION("ContainsKeyReturnsTrueForDefinedValue") {
_object.set("hello", 42); obj.set("hello", 42);
REQUIRE(true == _object.containsKey("hello")); REQUIRE(true == obj.containsKey("hello"));
} }
SECTION("ContainsKeyReturnsFalseAfterRemove") { SECTION("ContainsKeyReturnsFalseAfterRemove") {
_object.set("hello", 42); obj.set("hello", 42);
_object.remove("hello"); obj.remove("hello");
REQUIRE(false == _object.containsKey("hello")); REQUIRE(false == obj.containsKey("hello"));
} }
} }

View File

@ -8,7 +8,8 @@
using namespace Catch::Matchers; using namespace Catch::Matchers;
TEST_CASE("JsonObject::get()") { TEST_CASE("JsonObject::get()") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
SECTION("GetConstCharPointer_GivenStringLiteral") { SECTION("GetConstCharPointer_GivenStringLiteral") {
obj.set("hello", "world"); obj.set("hello", "world");

View File

@ -8,7 +8,8 @@
using namespace Catch::Matchers; using namespace Catch::Matchers;
TEST_CASE("JsonObject::begin()/end()") { TEST_CASE("JsonObject::begin()/end()") {
StaticJsonObject<JSON_OBJECT_SIZE(2)> obj; StaticJsonDocument<JSON_OBJECT_SIZE(2)> doc;
JsonObject& obj = doc.to<JsonObject>();
obj["ab"] = 12; obj["ab"] = 12;
obj["cd"] = 34; obj["cd"] = 34;

View File

@ -7,7 +7,8 @@
#include <string> #include <string>
TEST_CASE("JsonObject::remove()") { TEST_CASE("JsonObject::remove()") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
SECTION("SizeDecreased_WhenValuesAreRemoved") { SECTION("SizeDecreased_WhenValuesAreRemoved") {
obj["hello"] = 1; obj["hello"] = 1;
@ -26,7 +27,9 @@ TEST_CASE("JsonObject::remove()") {
} }
SECTION("RemoveByIterator") { SECTION("RemoveByIterator") {
deserializeJson(obj, "{\"a\":0,\"b\":1,\"c\":2}"); obj["a"] = 0;
obj["b"] = 1;
obj["c"] = 2;
for (JsonObject::iterator it = obj.begin(); it != obj.end(); ++it) { for (JsonObject::iterator it = obj.begin(); it != obj.end(); ++it) {
if (it->value == 1) obj.remove(it); if (it->value == 1) obj.remove(it);

View File

@ -7,129 +7,136 @@
#include <string> #include <string>
TEST_CASE("JsonObject::set()") { TEST_CASE("JsonObject::set()") {
DynamicJsonObject _object; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
SECTION("int") { SECTION("int") {
_object.set("hello", 123); obj.set("hello", 123);
REQUIRE(123 == _object["hello"].as<int>()); REQUIRE(123 == obj["hello"].as<int>());
REQUIRE(_object["hello"].is<int>()); REQUIRE(obj["hello"].is<int>());
REQUIRE_FALSE(_object["hello"].is<bool>()); REQUIRE_FALSE(obj["hello"].is<bool>());
} }
SECTION("double") { SECTION("double") {
_object.set("hello", 123.45); obj.set("hello", 123.45);
REQUIRE(123.45 == _object["hello"].as<double>()); REQUIRE(123.45 == obj["hello"].as<double>());
REQUIRE(_object["hello"].is<double>()); REQUIRE(obj["hello"].is<double>());
REQUIRE_FALSE(_object["hello"].is<bool>()); REQUIRE_FALSE(obj["hello"].is<bool>());
} }
SECTION("bool") { SECTION("bool") {
_object.set("hello", true); obj.set("hello", true);
REQUIRE(_object["hello"].as<bool>()); REQUIRE(obj["hello"].as<bool>());
REQUIRE(_object["hello"].is<bool>()); REQUIRE(obj["hello"].is<bool>());
REQUIRE_FALSE(_object["hello"].is<long>()); REQUIRE_FALSE(obj["hello"].is<long>());
} }
SECTION("const char*") { SECTION("const char*") {
_object.set("hello", "h3110"); obj.set("hello", "h3110");
REQUIRE(std::string("h3110") == _object["hello"].as<const char*>()); REQUIRE(std::string("h3110") == obj["hello"].as<const char*>());
REQUIRE(_object["hello"].is<const char*>()); REQUIRE(obj["hello"].is<const char*>());
REQUIRE_FALSE(_object["hello"].is<long>()); REQUIRE_FALSE(obj["hello"].is<long>());
} }
SECTION("nested array") { SECTION("nested array") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
_object.set("hello", arr); obj.set("hello", arr);
REQUIRE(&arr == &_object["hello"].as<JsonArray>()); REQUIRE(&arr == &obj["hello"].as<JsonArray>());
REQUIRE(_object["hello"].is<JsonArray&>()); REQUIRE(obj["hello"].is<JsonArray&>());
REQUIRE_FALSE(_object["hello"].is<JsonObject&>()); REQUIRE_FALSE(obj["hello"].is<JsonObject&>());
} }
SECTION("nested object") { SECTION("nested object") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
JsonObject& obj2 = doc2.to<JsonObject>();
_object.set("hello", obj); obj.set("hello", obj2);
REQUIRE(&obj == &_object["hello"].as<JsonObject>()); REQUIRE(&obj2 == &obj["hello"].as<JsonObject>());
REQUIRE(_object["hello"].is<JsonObject&>()); REQUIRE(obj["hello"].is<JsonObject&>());
REQUIRE_FALSE(_object["hello"].is<JsonArray&>()); REQUIRE_FALSE(obj["hello"].is<JsonArray&>());
} }
SECTION("array subscript") { SECTION("array subscript") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
arr.add(42); arr.add(42);
_object.set("a", arr[0]); obj.set("a", arr[0]);
REQUIRE(42 == _object["a"]); REQUIRE(42 == obj["a"]);
} }
SECTION("object subscript") { SECTION("object subscript") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
obj.set("x", 42); JsonObject& obj2 = doc2.to<JsonObject>();
obj2.set("x", 42);
_object.set("a", obj["x"]); obj.set("a", obj2["x"]);
REQUIRE(42 == _object["a"]); REQUIRE(42 == obj["a"]);
} }
SECTION("returns true when allocation succeeds") { SECTION("returns true when allocation succeeds") {
StaticJsonObject<JSON_OBJECT_SIZE(1) + 15> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1) + 15> doc2;
JsonObject& obj2 = doc2.to<JsonObject>();
REQUIRE(true == obj.set(std::string("hello"), std::string("world"))); REQUIRE(true == obj2.set(std::string("hello"), std::string("world")));
} }
SECTION("returns false when allocation fails") { SECTION("returns false when allocation fails") {
StaticJsonObject<JSON_OBJECT_SIZE(1) + 10> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1) + 10> doc2;
JsonObject& obj2 = doc2.to<JsonObject>();
REQUIRE(false == obj.set(std::string("hello"), std::string("world"))); REQUIRE(false == obj2.set(std::string("hello"), std::string("world")));
} }
SECTION("should not duplicate const char*") { SECTION("should not duplicate const char*") {
_object.set("hello", "world"); obj.set("hello", "world");
const size_t expectedSize = JSON_OBJECT_SIZE(1); const size_t expectedSize = JSON_OBJECT_SIZE(1);
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char* value") { SECTION("should duplicate char* value") {
_object.set("hello", const_cast<char*>("world")); obj.set("hello", const_cast<char*>("world"));
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char* key") { SECTION("should duplicate char* key") {
_object.set(const_cast<char*>("hello"), "world"); obj.set(const_cast<char*>("hello"), "world");
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char* key&value") { SECTION("should duplicate char* key&value") {
_object.set(const_cast<char*>("hello"), const_cast<char*>("world")); obj.set(const_cast<char*>("hello"), const_cast<char*>("world"));
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
REQUIRE(expectedSize <= _object.memoryUsage()); REQUIRE(expectedSize <= doc.memoryUsage());
} }
SECTION("should duplicate std::string value") { SECTION("should duplicate std::string value") {
_object.set("hello", std::string("world")); obj.set("hello", std::string("world"));
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate std::string key") { SECTION("should duplicate std::string key") {
_object.set(std::string("hello"), "world"); obj.set(std::string("hello"), "world");
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate std::string key&value") { SECTION("should duplicate std::string key&value") {
_object.set(std::string("hello"), std::string("world")); obj.set(std::string("hello"), std::string("world"));
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
REQUIRE(expectedSize <= _object.memoryUsage()); REQUIRE(expectedSize <= doc.memoryUsage());
} }
} }

View File

@ -7,16 +7,21 @@
#include <string> #include <string>
TEST_CASE("JsonObject::size()") { TEST_CASE("JsonObject::size()") {
DynamicJsonObject _object; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
SECTION("initial size is zero") {
REQUIRE(0 == obj.size());
}
SECTION("increases when values are added") { SECTION("increases when values are added") {
_object.set("hello", 42); obj.set("hello", 42);
REQUIRE(1 == _object.size()); REQUIRE(1 == obj.size());
} }
SECTION("doesn't increase when the smae key is added twice") { SECTION("doesn't increase when the smae key is added twice") {
_object["hello"] = 1; obj["hello"] = 1;
_object["hello"] = 2; obj["hello"] = 2;
REQUIRE(1 == _object.size()); REQUIRE(1 == obj.size());
} }
} }

View File

@ -6,146 +6,150 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("JsonObject::operator[]") { TEST_CASE("JsonObject::operator[]") {
DynamicJsonObject _object; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
SECTION("int") { SECTION("int") {
_object["hello"] = 123; obj["hello"] = 123;
REQUIRE(123 == _object["hello"].as<int>()); REQUIRE(123 == obj["hello"].as<int>());
REQUIRE(true == _object["hello"].is<int>()); REQUIRE(true == obj["hello"].is<int>());
REQUIRE(false == _object["hello"].is<bool>()); REQUIRE(false == obj["hello"].is<bool>());
} }
SECTION("volatile int") { // issue #415 SECTION("volatile int") { // issue #415
volatile int i = 123; volatile int i = 123;
_object["hello"] = i; obj["hello"] = i;
REQUIRE(123 == _object["hello"].as<int>()); REQUIRE(123 == obj["hello"].as<int>());
REQUIRE(true == _object["hello"].is<int>()); REQUIRE(true == obj["hello"].is<int>());
REQUIRE(false == _object["hello"].is<bool>()); REQUIRE(false == obj["hello"].is<bool>());
} }
SECTION("double") { SECTION("double") {
_object["hello"] = 123.45; obj["hello"] = 123.45;
REQUIRE(true == _object["hello"].is<double>()); REQUIRE(true == obj["hello"].is<double>());
REQUIRE(false == _object["hello"].is<long>()); REQUIRE(false == obj["hello"].is<long>());
REQUIRE(123.45 == _object["hello"].as<double>()); REQUIRE(123.45 == obj["hello"].as<double>());
} }
SECTION("bool") { SECTION("bool") {
_object["hello"] = true; obj["hello"] = true;
REQUIRE(true == _object["hello"].is<bool>()); REQUIRE(true == obj["hello"].is<bool>());
REQUIRE(false == _object["hello"].is<long>()); REQUIRE(false == obj["hello"].is<long>());
REQUIRE(true == _object["hello"].as<bool>()); REQUIRE(true == obj["hello"].as<bool>());
} }
SECTION("const char*") { SECTION("const char*") {
_object["hello"] = "h3110"; obj["hello"] = "h3110";
REQUIRE(true == _object["hello"].is<const char*>()); REQUIRE(true == obj["hello"].is<const char*>());
REQUIRE(false == _object["hello"].is<long>()); REQUIRE(false == obj["hello"].is<long>());
REQUIRE(std::string("h3110") == _object["hello"].as<const char*>()); REQUIRE(std::string("h3110") == obj["hello"].as<const char*>());
REQUIRE(std::string("h3110") == REQUIRE(std::string("h3110") == obj["hello"].as<char*>()); // <- short hand
_object["hello"].as<char*>()); // <- short hand
} }
SECTION("array") { SECTION("array") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
_object["hello"] = arr; obj["hello"] = arr;
REQUIRE(&arr == &_object["hello"].as<JsonArray&>()); REQUIRE(&arr == &obj["hello"].as<JsonArray&>());
REQUIRE(&arr == &_object["hello"].as<JsonArray>()); // <- short hand REQUIRE(&arr == &obj["hello"].as<JsonArray>()); // <- short hand
REQUIRE(&arr == &_object["hello"].as<const JsonArray&>()); REQUIRE(&arr == &obj["hello"].as<const JsonArray&>());
REQUIRE(&arr == &_object["hello"].as<const JsonArray>()); // <- short hand REQUIRE(&arr == &obj["hello"].as<const JsonArray>()); // <- short hand
REQUIRE(true == _object["hello"].is<JsonArray&>()); REQUIRE(true == obj["hello"].is<JsonArray&>());
REQUIRE(true == _object["hello"].is<JsonArray>()); REQUIRE(true == obj["hello"].is<JsonArray>());
REQUIRE(true == _object["hello"].is<const JsonArray&>()); REQUIRE(true == obj["hello"].is<const JsonArray&>());
REQUIRE(true == _object["hello"].is<const JsonArray>()); REQUIRE(true == obj["hello"].is<const JsonArray>());
REQUIRE(false == _object["hello"].is<JsonObject&>()); REQUIRE(false == obj["hello"].is<JsonObject&>());
} }
SECTION("object") { SECTION("object") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
JsonObject& obj2 = doc2.to<JsonObject>();
_object["hello"] = obj; obj["hello"] = obj2;
REQUIRE(&obj == &_object["hello"].as<JsonObject&>()); REQUIRE(&obj2 == &obj["hello"].as<JsonObject&>());
REQUIRE(&obj == &_object["hello"].as<JsonObject>()); // <- short hand REQUIRE(&obj2 == &obj["hello"].as<JsonObject>()); // <- short hand
REQUIRE(&obj == &_object["hello"].as<const JsonObject&>()); REQUIRE(&obj2 == &obj["hello"].as<const JsonObject&>());
REQUIRE(&obj == &_object["hello"].as<const JsonObject>()); // <- short hand REQUIRE(&obj2 == &obj["hello"].as<const JsonObject>()); // <- short hand
REQUIRE(true == _object["hello"].is<JsonObject&>()); REQUIRE(true == obj["hello"].is<JsonObject&>());
REQUIRE(true == _object["hello"].is<JsonObject>()); REQUIRE(true == obj["hello"].is<JsonObject>());
REQUIRE(true == _object["hello"].is<const JsonObject&>()); REQUIRE(true == obj["hello"].is<const JsonObject&>());
REQUIRE(true == _object["hello"].is<const JsonObject>()); REQUIRE(true == obj["hello"].is<const JsonObject>());
REQUIRE(false == _object["hello"].is<JsonArray&>()); REQUIRE(false == obj["hello"].is<JsonArray&>());
} }
SECTION("array subscript") { SECTION("array subscript") {
DynamicJsonArray arr; DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
arr.add(42); arr.add(42);
_object["a"] = arr[0]; obj["a"] = arr[0];
REQUIRE(42 == _object["a"]); REQUIRE(42 == obj["a"]);
} }
SECTION("object subscript") { SECTION("object subscript") {
DynamicJsonObject obj; DynamicJsonDocument doc2;
obj.set("x", 42); JsonObject& obj2 = doc2.to<JsonObject>();
obj2.set("x", 42);
_object["a"] = obj["x"]; obj["a"] = obj2["x"];
REQUIRE(42 == _object["a"]); REQUIRE(42 == obj["a"]);
} }
SECTION("char key[]") { // issue #423 SECTION("char key[]") { // issue #423
char key[] = "hello"; char key[] = "hello";
_object[key] = 42; obj[key] = 42;
REQUIRE(42 == _object[key]); REQUIRE(42 == obj[key]);
} }
SECTION("should not duplicate const char*") { SECTION("should not duplicate const char*") {
_object["hello"] = "world"; obj["hello"] = "world";
const size_t expectedSize = JSON_OBJECT_SIZE(1); const size_t expectedSize = JSON_OBJECT_SIZE(1);
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char* value") { SECTION("should duplicate char* value") {
_object["hello"] = const_cast<char*>("world"); obj["hello"] = const_cast<char*>("world");
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char* key") { SECTION("should duplicate char* key") {
_object[const_cast<char*>("hello")] = "world"; obj[const_cast<char*>("hello")] = "world";
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate char* key&value") { SECTION("should duplicate char* key&value") {
_object[const_cast<char*>("hello")] = const_cast<char*>("world"); obj[const_cast<char*>("hello")] = const_cast<char*>("world");
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
REQUIRE(expectedSize <= _object.memoryUsage()); REQUIRE(expectedSize <= doc.memoryUsage());
} }
SECTION("should duplicate std::string value") { SECTION("should duplicate std::string value") {
_object["hello"] = std::string("world"); obj["hello"] = std::string("world");
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate std::string key") { SECTION("should duplicate std::string key") {
_object[std::string("hello")] = "world"; obj[std::string("hello")] = "world";
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 6;
REQUIRE(expectedSize == _object.memoryUsage()); REQUIRE(expectedSize == doc.memoryUsage());
} }
SECTION("should duplicate std::string key&value") { SECTION("should duplicate std::string key&value") {
_object[std::string("hello")] = std::string("world"); obj[std::string("hello")] = std::string("world");
const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12; const size_t expectedSize = JSON_OBJECT_SIZE(1) + 12;
REQUIRE(expectedSize <= _object.memoryUsage()); REQUIRE(expectedSize <= doc.memoryUsage());
} }
} }

View File

@ -1,17 +0,0 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# MIT License
add_executable(JsonParserTests
DynamicJsonArray.cpp
DynamicJsonObject.cpp
DynamicJsonVariant.cpp
JsonError.cpp
nestingLimit.cpp
StaticJsonArray.cpp
StaticJsonObject.cpp
StaticJsonVariant.cpp
)
target_link_libraries(JsonParserTests catch)
add_test(JsonParser JsonParserTests)

View File

@ -1,98 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
using namespace Catch::Matchers;
TEST_CASE("deserializeJson(DynamicJsonVariant&)") {
DynamicJsonVariant variant;
SECTION("EmptyObject") {
JsonError err = deserializeJson(variant, "{}");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<JsonObject>());
}
SECTION("EmptyArray") {
JsonError err = deserializeJson(variant, "[]");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<JsonArray>());
}
SECTION("Integer") {
JsonError err = deserializeJson(variant, "-42");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<int>());
REQUIRE_FALSE(variant.is<bool>());
REQUIRE(variant == -42);
}
SECTION("Double") {
JsonError err = deserializeJson(variant, "-1.23e+4");
REQUIRE(err == JsonError::Ok);
REQUIRE_FALSE(variant.is<int>());
REQUIRE(variant.is<double>());
REQUIRE(variant.as<double>() == Approx(-1.23e+4));
}
SECTION("Double quoted string") {
JsonError err = deserializeJson(variant, "\"hello world\"");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<char*>());
REQUIRE_THAT(variant.as<char*>(), Equals("hello world"));
}
SECTION("Single quoted string") {
JsonError err = deserializeJson(variant, "\'hello world\'");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<char*>());
REQUIRE_THAT(variant.as<char*>(), Equals("hello world"));
}
SECTION("True") {
JsonError err = deserializeJson(variant, "true");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<bool>());
REQUIRE(variant == true);
}
SECTION("False") {
JsonError err = deserializeJson(variant, "false");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<bool>());
REQUIRE(variant == false);
}
SECTION("OpenBrace") {
JsonError err = deserializeJson(variant, "{");
REQUIRE(err != JsonError::Ok);
}
SECTION("Incomplete string") {
JsonError err = deserializeJson(variant, "\"hello");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<char*>());
REQUIRE_THAT(variant.as<char*>(), Equals("hello"));
}
SECTION("Should clear the JsonVariant") {
deserializeJson(variant, "[1,2,3]");
deserializeJson(variant, "{}");
REQUIRE(variant.is<JsonObject>());
REQUIRE(variant.memoryUsage() == JSON_OBJECT_SIZE(0));
}
}

View File

@ -1,90 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
TEST_CASE("deserializeJson(StaticJsonArray&)") {
SECTION("BufferOfTheRightSizeForEmptyArray") {
StaticJsonArray<JSON_ARRAY_SIZE(0)> arr;
char input[] = "[]";
JsonError err = deserializeJson(arr, input);
REQUIRE(err == JsonError::Ok);
}
SECTION("TooSmallBufferForArrayWithOneValue") {
StaticJsonArray<JSON_ARRAY_SIZE(1) - 1> arr;
char input[] = "[1]";
JsonError err = deserializeJson(arr, input);
REQUIRE(err != JsonError::Ok);
}
SECTION("BufferOfTheRightSizeForArrayWithOneValue") {
StaticJsonArray<JSON_ARRAY_SIZE(1)> arr;
char input[] = "[1]";
JsonError err = deserializeJson(arr, input);
REQUIRE(err == JsonError::Ok);
}
SECTION("TooSmallBufferForArrayWithNestedObject") {
StaticJsonArray<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0) - 1> arr;
char input[] = "[{}]";
JsonError err = deserializeJson(arr, input);
REQUIRE(err != JsonError::Ok);
}
SECTION("BufferOfTheRightSizeForArrayWithNestedObject") {
StaticJsonArray<JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(0)> arr;
char input[] = "[{}]";
JsonError err = deserializeJson(arr, input);
REQUIRE(err == JsonError::Ok);
}
SECTION("CharPtrNull") {
StaticJsonArray<100> arr;
JsonError err = deserializeJson(arr, static_cast<char*>(0));
REQUIRE(err != JsonError::Ok);
}
SECTION("ConstCharPtrNull") {
StaticJsonArray<100> arr;
JsonError err = deserializeJson(arr, static_cast<const char*>(0));
REQUIRE(err != JsonError::Ok);
}
SECTION("CopyStringNotSpaces") {
StaticJsonArray<100> arr;
deserializeJson(arr, " [ \"1234567\" ] ");
REQUIRE(JSON_ARRAY_SIZE(1) + sizeof("1234567") == arr.memoryUsage());
// note: we use a string of 8 bytes to be sure that the StaticJsonBuffer
// will not insert bytes to enforce alignement
}
SECTION("Should clear the JsonArray") {
StaticJsonArray<JSON_ARRAY_SIZE(4)> arr;
char input[] = "[1,2,3,4]";
deserializeJson(arr, input);
deserializeJson(arr, "[]");
REQUIRE(arr.size() == 0);
REQUIRE(arr.memoryUsage() == JSON_ARRAY_SIZE(0));
}
}

View File

@ -1,35 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
using namespace Catch::Matchers;
TEST_CASE("deserializeJson(StaticJsonVariant&)") {
SECTION("Array") {
StaticJsonVariant<JSON_ARRAY_SIZE(2)> variant;
char input[] = "[1,2]";
JsonError err = deserializeJson(variant, input);
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<JsonArray>());
REQUIRE(variant[0] == 1);
REQUIRE(variant[1] == 2);
REQUIRE(variant.memoryUsage() == JSON_ARRAY_SIZE(2));
}
SECTION("Should clear the JsonVariant") {
StaticJsonVariant<JSON_ARRAY_SIZE(2)> variant;
char input[] = "[1,2]";
deserializeJson(variant, input);
JsonError err = deserializeJson(variant, "{}");
REQUIRE(err == JsonError::Ok);
REQUIRE(variant.is<JsonObject>());
REQUIRE(variant.memoryUsage() == JSON_OBJECT_SIZE(0));
}
}

View File

@ -1,70 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
#define SHOULD_WORK(expression) REQUIRE(JsonError::Ok == expression);
#define SHOULD_FAIL(expression) REQUIRE(JsonError::TooDeep == expression);
TEST_CASE("JsonParser nestingLimit") {
SECTION("deserializeJson(JsonArray&)") {
DynamicJsonArray arr;
SECTION("limit = 0") {
SHOULD_FAIL(deserializeJson(arr, "[]", 0));
}
SECTION("limit = 1") {
SHOULD_WORK(deserializeJson(arr, "[]", 1));
SHOULD_FAIL(deserializeJson(arr, "[[]]", 1));
}
SECTION("limit = 2") {
SHOULD_WORK(deserializeJson(arr, "[[]]", 2));
SHOULD_FAIL(deserializeJson(arr, "[[[]]]", 2));
}
}
SECTION("deserializeJson(JsonObject&)") {
DynamicJsonObject obj;
SECTION("limit = 0") {
SHOULD_FAIL(deserializeJson(obj, "{}", 0));
}
SECTION("limit = 1") {
SHOULD_WORK(deserializeJson(obj, "{\"key\":42}", 1));
SHOULD_FAIL(deserializeJson(obj, "{\"key\":{\"key\":42}}", 1));
}
SECTION("limit = 2") {
SHOULD_WORK(deserializeJson(obj, "{\"key\":{\"key\":42}}", 2));
SHOULD_FAIL(deserializeJson(obj, "{\"key\":{\"key\":{\"key\":42}}}", 2));
}
}
SECTION("deserializeJson(JsonVariant&)") {
DynamicJsonVariant var;
SECTION("limit = 0") {
SHOULD_WORK(deserializeJson(var, "\"toto\"", 0));
SHOULD_WORK(deserializeJson(var, "123", 0));
SHOULD_WORK(deserializeJson(var, "true", 0));
SHOULD_FAIL(deserializeJson(var, "[]", 0));
SHOULD_FAIL(deserializeJson(var, "{}", 0));
SHOULD_FAIL(deserializeJson(var, "[\"toto\"]", 0));
SHOULD_FAIL(deserializeJson(var, "{\"toto\":1}", 0));
}
SECTION("limit = 1") {
SHOULD_WORK(deserializeJson(var, "[\"toto\"]", 1));
SHOULD_WORK(deserializeJson(var, "{\"toto\":1}", 1));
SHOULD_FAIL(deserializeJson(var, "{\"toto\":{}}", 1));
SHOULD_FAIL(deserializeJson(var, "{\"toto\":[]}", 1));
SHOULD_FAIL(deserializeJson(var, "[[\"toto\"]]", 1));
SHOULD_FAIL(deserializeJson(var, "[{\"toto\":1}]", 1));
}
}
}

View File

@ -15,7 +15,8 @@ static void check(JsonArray &array, std::string expected) {
} }
TEST_CASE("serializeJson(JsonArray)") { TEST_CASE("serializeJson(JsonArray)") {
StaticJsonArray<JSON_ARRAY_SIZE(2)> array; StaticJsonDocument<JSON_ARRAY_SIZE(2)> doc;
JsonArray &array = doc.to<JsonArray>();
SECTION("Empty") { SECTION("Empty") {
check(array, "[]"); check(array, "[]");

View File

@ -15,7 +15,8 @@ static void check(JsonArray& array, std::string expected) {
} }
TEST_CASE("serializeJsonPretty(JsonArray)") { TEST_CASE("serializeJsonPretty(JsonArray)") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
SECTION("Empty") { SECTION("Empty") {
check(array, "[]"); check(array, "[]");

View File

@ -17,7 +17,8 @@ void check(const JsonObject &obj, const std::string &expected) {
} }
TEST_CASE("serializeJson(JsonObject)") { TEST_CASE("serializeJson(JsonObject)") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject &obj = doc.to<JsonObject>();
SECTION("EmptyObject") { SECTION("EmptyObject") {
check(obj, "{}"); check(obj, "{}");
@ -92,22 +93,23 @@ TEST_CASE("serializeJson(JsonObject)") {
} }
SECTION("ThreeNestedArrays") { SECTION("ThreeNestedArrays") {
DynamicJsonArray b, c; DynamicJsonDocument b;
DynamicJsonDocument c;
obj.createNestedArray("a"); obj.createNestedArray("a");
obj["b"] = b; obj["b"] = b.to<JsonArray>();
obj.set("c", c); obj.set("c", c.to<JsonArray>());
check(obj, "{\"a\":[],\"b\":[],\"c\":[]}"); check(obj, "{\"a\":[],\"b\":[],\"c\":[]}");
} }
SECTION("ThreeNestedObjects") { SECTION("ThreeNestedObjects") {
DynamicJsonObject b; DynamicJsonDocument b;
DynamicJsonObject c; DynamicJsonDocument c;
obj.createNestedObject("a"); obj.createNestedObject("a");
obj["b"] = b; obj["b"] = b.to<JsonObject>();
obj.set("c", c); obj.set("c", c.to<JsonObject>());
check(obj, "{\"a\":{},\"b\":{},\"c\":{}}"); check(obj, "{\"a\":{},\"b\":{},\"c\":{}}");
} }

View File

@ -18,7 +18,8 @@ void check(const JsonObject &obj, const std::string expected) {
} }
TEST_CASE("serializeJsonPretty(JsonObject)") { TEST_CASE("serializeJsonPretty(JsonObject)") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject &obj = doc.to<JsonObject>();
SECTION("EmptyObject") { SECTION("EmptyObject") {
check(obj, "{}"); check(obj, "{}");

View File

@ -192,7 +192,8 @@ TEST_CASE("JsonVariant::as()") {
} }
SECTION("ObjectAsString") { SECTION("ObjectAsString") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj["key"] = "value"; obj["key"] = "value";
@ -201,7 +202,8 @@ TEST_CASE("JsonVariant::as()") {
} }
SECTION("ArrayAsString") { SECTION("ArrayAsString") {
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add(4); arr.add(4);
arr.add(2); arr.add(2);
@ -210,7 +212,8 @@ TEST_CASE("JsonVariant::as()") {
} }
SECTION("ArrayAsJsonArray") { SECTION("ArrayAsJsonArray") {
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
JsonVariant variant = arr; JsonVariant variant = arr;
REQUIRE(&arr == &variant.as<JsonArray&>()); REQUIRE(&arr == &variant.as<JsonArray&>());
@ -218,7 +221,8 @@ TEST_CASE("JsonVariant::as()") {
} }
SECTION("ObjectAsJsonObject") { SECTION("ObjectAsJsonObject") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
JsonVariant variant = obj; JsonVariant variant = obj;
REQUIRE(&obj == &variant.as<JsonObject&>()); REQUIRE(&obj == &variant.as<JsonObject&>());

View File

@ -97,8 +97,9 @@ TEST_CASE("JsonVariant comparisons") {
} }
SECTION("StringLiteral") { SECTION("StringLiteral") {
DynamicJsonVariant variant; DynamicJsonDocument doc;
deserializeJson(variant, "\"hello\""); deserializeJson(doc, "\"hello\"");
JsonVariant variant = doc.as<JsonVariant>();
REQUIRE(variant == "hello"); REQUIRE(variant == "hello");
REQUIRE_FALSE(variant != "hello"); REQUIRE_FALSE(variant != "hello");
@ -114,8 +115,7 @@ TEST_CASE("JsonVariant comparisons") {
} }
SECTION("String") { SECTION("String") {
DynamicJsonVariant variant; JsonVariant variant = "hello";
deserializeJson(variant, "\"hello\"");
REQUIRE(variant == std::string("hello")); REQUIRE(variant == std::string("hello"));
REQUIRE_FALSE(variant != std::string("hello")); REQUIRE_FALSE(variant != std::string("hello"));
@ -179,7 +179,10 @@ TEST_CASE("JsonVariant comparisons") {
} }
SECTION("ArrayInVariant") { SECTION("ArrayInVariant") {
DynamicJsonArray array1, array2; DynamicJsonDocument doc1;
JsonArray& array1 = doc1.to<JsonArray>();
DynamicJsonDocument doc2;
JsonArray& array2 = doc2.to<JsonArray>();
JsonVariant variant1 = array1; JsonVariant variant1 = array1;
JsonVariant variant2 = array1; JsonVariant variant2 = array1;
@ -193,8 +196,10 @@ TEST_CASE("JsonVariant comparisons") {
} }
SECTION("ObjectInVariant") { SECTION("ObjectInVariant") {
DynamicJsonObject obj1; DynamicJsonDocument doc1;
DynamicJsonObject obj2; JsonObject& obj1 = doc1.to<JsonObject>();
DynamicJsonDocument doc2;
JsonObject& obj2 = doc2.to<JsonObject>();
JsonVariant variant1 = obj1; JsonVariant variant1 = obj1;
JsonVariant variant2 = obj1; JsonVariant variant2 = obj1;
@ -208,8 +213,11 @@ TEST_CASE("JsonVariant comparisons") {
} }
SECTION("VariantsOfDifferentTypes") { SECTION("VariantsOfDifferentTypes") {
DynamicJsonObject obj; DynamicJsonDocument doc1;
DynamicJsonArray arr; JsonObject& obj = doc1.to<JsonObject>();
DynamicJsonDocument doc2;
JsonArray& arr = doc2.to<JsonArray>();
JsonVariant variants[] = { JsonVariant variants[] = {
true, 42, 666.667, "hello", arr, obj, true, 42, 666.667, "hello", arr, obj,
}; };

View File

@ -38,11 +38,12 @@ TEST_CASE("JsonVariant copy") {
_variant2 = _variant1; _variant2 = _variant1;
_variant1 = "world"; _variant1 = "world";
REQUIRE(std::string("hello") == _variant2.as<const char *>()); REQUIRE(std::string("hello") == _variant2.as<const char*>());
} }
SECTION("ObjectsAreCopiedByReference") { SECTION("ObjectsAreCopiedByReference") {
DynamicJsonObject object; DynamicJsonDocument doc;
JsonObject& object = doc.to<JsonObject>();
_variant1 = object; _variant1 = object;
@ -52,7 +53,8 @@ TEST_CASE("JsonVariant copy") {
} }
SECTION("ArraysAreCopiedByReference") { SECTION("ArraysAreCopiedByReference") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
_variant1 = array; _variant1 = array;

View File

@ -69,10 +69,9 @@ void checkIsString(JsonVariant var) {
} }
TEST_CASE("JsonVariant::is()") { TEST_CASE("JsonVariant::is()") {
DynamicJsonBuffer jsonBuffer;
SECTION("JsonArray") { SECTION("JsonArray") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
checkIsArray(array); checkIsArray(array);
} }

View File

@ -122,7 +122,8 @@ TEST_CASE("JsonVariant set()/get()") {
#endif #endif
SECTION("CanStoreObject") { SECTION("CanStoreObject") {
DynamicJsonObject object; DynamicJsonDocument doc;
JsonObject &object = doc.to<JsonObject>();
checkReference<JsonObject>(object); checkReference<JsonObject>(object);
} }

View File

@ -7,7 +7,8 @@
TEST_CASE("JsonVariant::operator[]") { TEST_CASE("JsonVariant::operator[]") {
SECTION("Array") { SECTION("Array") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
array.add("element at index 0"); array.add("element at index 0");
array.add("element at index 1"); array.add("element at index 1");
@ -24,7 +25,8 @@ TEST_CASE("JsonVariant::operator[]") {
} }
SECTION("Object") { SECTION("Object") {
DynamicJsonObject object; DynamicJsonDocument doc;
JsonObject& object = doc.to<JsonObject>();
object["a"] = "element at key \"a\""; object["a"] = "element at key \"a\"";
object["b"] = "element at key \"b\""; object["b"] = "element at key \"b\"";
@ -52,7 +54,8 @@ TEST_CASE("JsonVariant::operator[]") {
} }
SECTION("ObjectSetValue") { SECTION("ObjectSetValue") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
JsonVariant var = obj; JsonVariant var = obj;
var["hello"] = "world"; var["hello"] = "world";
REQUIRE(1 == var.size()); REQUIRE(1 == var.size());
@ -60,16 +63,19 @@ TEST_CASE("JsonVariant::operator[]") {
} }
SECTION("ArraySetValue") { SECTION("ArraySetValue") {
DynamicJsonVariant var; DynamicJsonDocument doc;
deserializeJson(var, "[\"hello\"]"); JsonArray& arr = doc.to<JsonArray>();
arr.add("hello");
JsonVariant var = arr;
var[0] = "world"; var[0] = "world";
REQUIRE(1 == var.size()); REQUIRE(1 == var.size());
REQUIRE(std::string("world") == var[0]); REQUIRE(std::string("world") == var[0]);
} }
SECTION("NestedObjectSetValue") { SECTION("NestedObjectSetValue") {
DynamicJsonVariant var; DynamicJsonDocument doc;
deserializeJson(var, "[{}]"); deserializeJson(doc, "[{}]");
JsonVariant var = doc.as<JsonVariant>();
var[0]["hello"] = "world"; var[0]["hello"] = "world";
REQUIRE(1 == var.size()); REQUIRE(1 == var.size());
REQUIRE(1 == var[0].size()); REQUIRE(1 == var[0].size());

View File

@ -17,14 +17,16 @@ TEST_CASE("JsonVariant::success()") {
} }
SECTION("ReturnsTrue_WhenEmptyArray") { SECTION("ReturnsTrue_WhenEmptyArray") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
JsonVariant variant = array; JsonVariant variant = array;
REQUIRE(true == variant.success()); REQUIRE(true == variant.success());
} }
SECTION("ReturnsTrue_WhenEmptyObject") { SECTION("ReturnsTrue_WhenEmptyObject") {
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
JsonVariant variant = obj; JsonVariant variant = obj;
REQUIRE(true == variant.success()); REQUIRE(true == variant.success());

View File

@ -23,7 +23,8 @@ TEST_CASE("std::stream") {
SECTION("JsonObject") { SECTION("JsonObject") {
std::ostringstream os; std::ostringstream os;
DynamicJsonObject object; DynamicJsonDocument doc;
JsonObject& object = doc.to<JsonObject>();
object["key"] = "value"; object["key"] = "value";
os << object; os << object;
REQUIRE("{\"key\":\"value\"}" == os.str()); REQUIRE("{\"key\":\"value\"}" == os.str());
@ -31,7 +32,8 @@ TEST_CASE("std::stream") {
SECTION("JsonObjectSubscript") { SECTION("JsonObjectSubscript") {
std::ostringstream os; std::ostringstream os;
DynamicJsonObject object; DynamicJsonDocument doc;
JsonObject& object = doc.to<JsonObject>();
object["key"] = "value"; object["key"] = "value";
os << object["key"]; os << object["key"];
REQUIRE("\"value\"" == os.str()); REQUIRE("\"value\"" == os.str());
@ -39,7 +41,8 @@ TEST_CASE("std::stream") {
SECTION("JsonArray") { SECTION("JsonArray") {
std::ostringstream os; std::ostringstream os;
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
array.add("value"); array.add("value");
os << array; os << array;
REQUIRE("[\"value\"]" == os.str()); REQUIRE("[\"value\"]" == os.str());
@ -47,7 +50,8 @@ TEST_CASE("std::stream") {
SECTION("JsonArraySubscript") { SECTION("JsonArraySubscript") {
std::ostringstream os; std::ostringstream os;
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray& array = doc.to<JsonArray>();
array.add("value"); array.add("value");
os << array[0]; os << array[0];
REQUIRE("\"value\"" == os.str()); REQUIRE("\"value\"" == os.str());
@ -55,8 +59,9 @@ TEST_CASE("std::stream") {
SECTION("ParseArray") { SECTION("ParseArray") {
std::istringstream json(" [ 42 /* comment */ ] "); std::istringstream json(" [ 42 /* comment */ ] ");
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonError err = deserializeJson(arr, json); JsonError err = deserializeJson(doc, json);
JsonArray& arr = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == arr.size()); REQUIRE(1 == arr.size());
@ -65,8 +70,9 @@ TEST_CASE("std::stream") {
SECTION("ParseObject") { SECTION("ParseObject") {
std::istringstream json(" { hello : world // comment\n }"); std::istringstream json(" { hello : world // comment\n }");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonError err = deserializeJson(obj, json); JsonError err = deserializeJson(doc, json);
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(1 == obj.size()); REQUIRE(1 == obj.size());
@ -75,8 +81,8 @@ TEST_CASE("std::stream") {
SECTION("ShouldNotReadPastTheEnd") { SECTION("ShouldNotReadPastTheEnd") {
std::istringstream json("{}123"); std::istringstream json("{}123");
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, json); deserializeJson(doc, json);
REQUIRE('1' == json.get()); REQUIRE('1' == json.get());
} }
} }

View File

@ -11,20 +11,21 @@ static void eraseString(std::string &str) {
} }
TEST_CASE("std::string") { TEST_CASE("std::string") {
DynamicJsonBuffer jb; SECTION("deserializeJson duplicates content") {
std::string json("[\"hello\"]");
DynamicJsonDocument doc;
JsonError err = deserializeJson(doc, json);
eraseString(json);
JsonArray &array = doc.as<JsonArray>();
REQUIRE(err == JsonError::Ok);
REQUIRE(std::string("hello") == array[0]);
}
SECTION("JsonArray") { SECTION("JsonArray") {
DynamicJsonArray array; DynamicJsonDocument doc;
JsonArray &array = doc.to<JsonArray>();
SECTION("deserializeJson") {
std::string json("[\"hello\"]");
JsonError err = deserializeJson(array, json);
eraseString(json);
REQUIRE(err == JsonError::Ok);
REQUIRE(std::string("hello") == array[0]);
}
SECTION("add()") { SECTION("add()") {
std::string value("hello"); std::string value("hello");
@ -67,168 +68,190 @@ TEST_CASE("std::string") {
} }
SECTION("JsonObject") { SECTION("JsonObject") {
DynamicJsonObject object; DynamicJsonDocument doc;
SECTION("deserializeJson()") { SECTION("deserializeJson()") {
std::string json("{\"hello\":\"world\"}"); std::string json("{\"hello\":\"world\"}");
JsonError err = deserializeJson(object, json); JsonError err = deserializeJson(doc, json);
JsonObject &obj = doc.as<JsonObject>();
eraseString(json); eraseString(json);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("operator[]") { SECTION("operator[]") {
char json[] = "{\"key\":\"value\"}"; char json[] = "{\"key\":\"value\"}";
deserializeJson(object, json); deserializeJson(doc, json);
JsonObject &obj = doc.as<JsonObject>();
REQUIRE(std::string("value") == object[std::string("key")]); REQUIRE(std::string("value") == obj[std::string("key")]);
} }
SECTION("operator[] const") { SECTION("operator[] const") {
char json[] = "{\"key\":\"value\"}"; char json[] = "{\"key\":\"value\"}";
deserializeJson(object, json); deserializeJson(doc, json);
const JsonObject &obj = object; JsonObject &obj = doc.as<JsonObject>();
REQUIRE(std::string("value") == obj[std::string("key")]); REQUIRE(std::string("value") == obj[std::string("key")]);
} }
SECTION("set(key)") { SECTION("set(key)") {
JsonObject &obj = doc.to<JsonObject>();
std::string key("hello"); std::string key("hello");
object.set(key, "world"); obj.set(key, "world");
eraseString(key); eraseString(key);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("set(value)") { SECTION("set(value)") {
JsonObject &obj = doc.to<JsonObject>();
std::string value("world"); std::string value("world");
object.set("hello", value); obj.set("hello", value);
eraseString(value); eraseString(value);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("set(key,value)") { SECTION("set(key,value)") {
JsonObject &obj = doc.to<JsonObject>();
std::string key("hello"); std::string key("hello");
std::string value("world"); std::string value("world");
object.set(key, value); obj.set(key, value);
eraseString(key); eraseString(key);
eraseString(value); eraseString(value);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("set(JsonArraySubscript)") { SECTION("set(JsonArraySubscript)") {
DynamicJsonArray arr; JsonObject &obj = doc.to<JsonObject>();
DynamicJsonDocument doc2;
JsonArray &arr = doc2.to<JsonArray>();
arr.add("world"); arr.add("world");
object.set(std::string("hello"), arr[0]); obj.set(std::string("hello"), arr[0]);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("set(JsonObjectSubscript)") { SECTION("set(JsonObjectSubscript)") {
DynamicJsonObject obj; JsonObject &obj = doc.to<JsonObject>();
obj.set("x", "world"); DynamicJsonDocument doc2;
JsonObject &obj2 = doc2.to<JsonObject>();
obj2.set("x", "world");
object.set(std::string("hello"), obj["x"]); obj.set(std::string("hello"), obj2["x"]);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("get<T>()") { SECTION("get<T>()") {
char json[] = "{\"key\":\"value\"}"; char json[] = "{\"key\":\"value\"}";
deserializeJson(object, json); deserializeJson(doc, json);
JsonObject &obj = doc.as<JsonObject>();
REQUIRE(std::string("value") == REQUIRE(std::string("value") ==
object.get<const char *>(std::string("key"))); obj.get<const char *>(std::string("key")));
} }
SECTION("is<T>()") { SECTION("is<T>()") {
char json[] = "{\"key\":\"value\"}"; char json[] = "{\"key\":\"value\"}";
deserializeJson(object, json); deserializeJson(doc, json);
REQUIRE(true == object.is<const char *>(std::string("key"))); JsonObject &obj = doc.as<JsonObject>();
REQUIRE(true == obj.is<const char *>(std::string("key")));
} }
SECTION("createNestedObject()") { SECTION("createNestedObject()") {
JsonObject &obj = doc.to<JsonObject>();
std::string key = "key"; std::string key = "key";
char json[64]; char json[64];
object.createNestedObject(key); obj.createNestedObject(key);
eraseString(key); eraseString(key);
serializeJson(object, json, sizeof(json)); serializeJson(doc, json, sizeof(json));
REQUIRE(std::string("{\"key\":{}}") == json); REQUIRE(std::string("{\"key\":{}}") == json);
} }
SECTION("createNestedArray()") { SECTION("createNestedArray()") {
JsonObject &obj = doc.to<JsonObject>();
std::string key = "key"; std::string key = "key";
char json[64]; char json[64];
object.createNestedArray(key); obj.createNestedArray(key);
eraseString(key); eraseString(key);
serializeJson(object, json, sizeof(json)); serializeJson(doc, json, sizeof(json));
REQUIRE(std::string("{\"key\":[]}") == json); REQUIRE(std::string("{\"key\":[]}") == json);
} }
SECTION("containsKey()") { SECTION("containsKey()") {
char json[] = "{\"key\":\"value\"}"; char json[] = "{\"key\":\"value\"}";
deserializeJson(object, json); deserializeJson(doc, json);
REQUIRE(true == object.containsKey(std::string("key"))); JsonObject &obj = doc.as<JsonObject>();
REQUIRE(true == obj.containsKey(std::string("key")));
} }
SECTION("remove()") { SECTION("remove()") {
char json[] = "{\"key\":\"value\"}"; JsonObject &obj = doc.to<JsonObject>();
deserializeJson(object, json); obj["key"] = "value";
REQUIRE(1 == object.size());
object.remove(std::string("key")); obj.remove(std::string("key"));
REQUIRE(0 == object.size());
REQUIRE(0 == obj.size());
} }
SECTION("operator[], set key") { SECTION("operator[], set key") {
std::string key("hello"); std::string key("hello");
object[key] = "world"; JsonObject &obj = doc.to<JsonObject>();
obj[key] = "world";
eraseString(key); eraseString(key);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("operator[], set value") { SECTION("operator[], set value") {
std::string value("world"); std::string value("world");
object["hello"] = value; JsonObject &obj = doc.to<JsonObject>();
obj["hello"] = value;
eraseString(value); eraseString(value);
REQUIRE(std::string("world") == object["hello"]); REQUIRE(std::string("world") == obj["hello"]);
} }
SECTION("serializeJson()") { SECTION("serializeJson()") {
object["key"] = "value"; JsonObject &obj = doc.to<JsonObject>();
obj["key"] = "value";
std::string json; std::string json;
serializeJson(object, json); serializeJson(doc, json);
REQUIRE(std::string("{\"key\":\"value\"}") == json); REQUIRE(std::string("{\"key\":\"value\"}") == json);
} }
SECTION("serializeJsonPretty()") { SECTION("serializeJsonPretty()") {
object["key"] = "value"; JsonObject &obj = doc.to<JsonObject>();
obj["key"] = "value";
std::string json; std::string json;
serializeJsonPretty(object, json); serializeJsonPretty(doc, json);
REQUIRE(std::string("{\r\n \"key\": \"value\"\r\n}") == json); REQUIRE(std::string("{\r\n \"key\": \"value\"\r\n}") == json);
} }
SECTION("memoryUsage() increases when adding a new key") { SECTION("memoryUsage() increases when adding a new key") {
std::string key1("hello"), key2("world"); std::string key1("hello"), key2("world");
JsonObject &obj = doc.to<JsonObject>();
object[key1] = 1; obj[key1] = 1;
size_t sizeBefore = object.memoryUsage(); size_t sizeBefore = doc.memoryUsage();
object[key2] = 2; obj[key2] = 2;
size_t sizeAfter = object.memoryUsage(); size_t sizeAfter = doc.memoryUsage();
REQUIRE(sizeAfter - sizeBefore >= key2.size()); REQUIRE(sizeAfter - sizeBefore >= key2.size());
} }
SECTION("memoryUsage() remains when adding the same key") { SECTION("memoryUsage() remains when adding the same key") {
std::string key("hello"); std::string key("hello");
JsonObject &obj = doc.to<JsonObject>();
object[key] = 1; obj[key] = 1;
size_t sizeBefore = object.memoryUsage(); size_t sizeBefore = doc.memoryUsage();
object[key] = 2; obj[key] = 2;
size_t sizeAfter = object.memoryUsage(); size_t sizeAfter = doc.memoryUsage();
REQUIRE(sizeBefore == sizeAfter); REQUIRE(sizeBefore == sizeAfter);
} }

View File

@ -13,8 +13,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonBuffer::parseArray") { SECTION("JsonBuffer::parseArray") {
unsigned char json[] = "[42]"; unsigned char json[] = "[42]";
StaticJsonArray<JSON_ARRAY_SIZE(1)> arr; StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
JsonError err = deserializeJson(arr, json); JsonError err = deserializeJson(doc, json);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
} }
@ -22,8 +22,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonBuffer::parseObject") { SECTION("JsonBuffer::parseObject") {
unsigned char json[] = "{\"a\":42}"; unsigned char json[] = "{\"a\":42}";
StaticJsonObject<JSON_OBJECT_SIZE(1)> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
JsonError err = deserializeJson(obj, json); JsonError err = deserializeJson(doc, json);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
} }
@ -49,8 +49,9 @@ TEST_CASE("unsigned char string") {
SECTION("JsonVariant::operator[]") { SECTION("JsonVariant::operator[]") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonVariant variant; DynamicJsonDocument doc;
deserializeJson(variant, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonVariant variant = doc.as<JsonVariant>();
REQUIRE(std::string("world") == variant[key]); REQUIRE(std::string("world") == variant[key]);
} }
@ -60,8 +61,9 @@ TEST_CASE("unsigned char string") {
SECTION("JsonVariant::operator[] const") { SECTION("JsonVariant::operator[] const") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonVariant variant; DynamicJsonDocument doc;
deserializeJson(variant, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
const JsonVariant variant = doc.as<JsonVariant>();
REQUIRE(std::string("world") == variant[key]); REQUIRE(std::string("world") == variant[key]);
} }
@ -70,7 +72,7 @@ TEST_CASE("unsigned char string") {
SECTION("JsonVariant::operator==") { SECTION("JsonVariant::operator==") {
unsigned char comparand[] = "hello"; unsigned char comparand[] = "hello";
DynamicJsonVariant variant; JsonVariant variant;
variant = "hello"; variant = "hello";
REQUIRE(comparand == variant); REQUIRE(comparand == variant);
@ -82,7 +84,7 @@ TEST_CASE("unsigned char string") {
SECTION("JsonVariant::operator!=") { SECTION("JsonVariant::operator!=") {
unsigned char comparand[] = "hello"; unsigned char comparand[] = "hello";
DynamicJsonVariant variant; JsonVariant variant;
variant = "world"; variant = "world";
REQUIRE(comparand != variant); REQUIRE(comparand != variant);
@ -95,7 +97,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::operator[]") { SECTION("JsonObject::operator[]") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj[key] = "world"; obj[key] = "world";
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -105,7 +108,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObjectSubscript::operator=") { // issue #416 SECTION("JsonObjectSubscript::operator=") { // issue #416
unsigned char value[] = "world"; unsigned char value[] = "world";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj["hello"] = value; obj["hello"] = value;
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -114,7 +118,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObjectSubscript::set()") { SECTION("JsonObjectSubscript::set()") {
unsigned char value[] = "world"; unsigned char value[] = "world";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj["hello"].set(value); obj["hello"].set(value);
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -124,9 +129,10 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::operator[] const") { SECTION("JsonObject::operator[] const") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(std::string("world") == obj[key]); REQUIRE(std::string("world") == obj[key]);
} }
#endif #endif
@ -134,16 +140,17 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::get()") { SECTION("JsonObject::get()") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(std::string("world") == obj.get<char*>(key)); REQUIRE(std::string("world") == obj.get<char*>(key));
} }
SECTION("JsonObject::set() key") { SECTION("JsonObject::set() key") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.set(key, "world"); obj.set(key, "world");
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -152,7 +159,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::set() value") { SECTION("JsonObject::set() value") {
unsigned char value[] = "world"; unsigned char value[] = "world";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.set("hello", value); obj.set("hello", value);
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -161,7 +169,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::set key&value") { SECTION("JsonObject::set key&value") {
unsigned char key[] = "world"; unsigned char key[] = "world";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.set(key, key); obj.set(key, key);
REQUIRE(std::string("world") == obj["world"]); REQUIRE(std::string("world") == obj["world"]);
@ -170,17 +179,18 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::containsKey()") { SECTION("JsonObject::containsKey()") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(true == obj.containsKey(key)); REQUIRE(true == obj.containsKey(key));
} }
SECTION("JsonObject::remove()") { SECTION("JsonObject::remove()") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
obj.remove(key); obj.remove(key);
REQUIRE(0 == obj.size()); REQUIRE(0 == obj.size());
@ -189,8 +199,9 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::is()") { SECTION("JsonObject::is()") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":42}"); deserializeJson(doc, "{\"hello\":42}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(true == obj.is<int>(key)); REQUIRE(true == obj.is<int>(key));
} }
@ -198,21 +209,24 @@ TEST_CASE("unsigned char string") {
SECTION("JsonObject::createNestedArray()") { SECTION("JsonObject::createNestedArray()") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.createNestedArray(key); obj.createNestedArray(key);
} }
SECTION("JsonObject::createNestedObject()") { SECTION("JsonObject::createNestedObject()") {
unsigned char key[] = "hello"; unsigned char key[] = "hello";
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.createNestedObject(key); obj.createNestedObject(key);
} }
SECTION("JsonArray::add()") { SECTION("JsonArray::add()") {
unsigned char value[] = "world"; unsigned char value[] = "world";
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add(value); arr.add(value);
REQUIRE(std::string("world") == arr[0]); REQUIRE(std::string("world") == arr[0]);
@ -221,7 +235,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonArray::set()") { SECTION("JsonArray::set()") {
unsigned char value[] = "world"; unsigned char value[] = "world";
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add("hello"); arr.add("hello");
arr.set(0, value); arr.set(0, value);
@ -231,7 +246,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonArraySubscript::set()") { SECTION("JsonArraySubscript::set()") {
unsigned char value[] = "world"; unsigned char value[] = "world";
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add("hello"); arr.add("hello");
arr[0].set(value); arr[0].set(value);
@ -241,7 +257,8 @@ TEST_CASE("unsigned char string") {
SECTION("JsonArraySubscript::operator=") { SECTION("JsonArraySubscript::operator=") {
unsigned char value[] = "world"; unsigned char value[] = "world";
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add("hello"); arr.add("hello");
arr[0] = value; arr[0] = value;

View File

@ -22,8 +22,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "[42]"); strcpy(vla, "[42]");
StaticJsonArray<JSON_ARRAY_SIZE(1)> arr; StaticJsonDocument<JSON_ARRAY_SIZE(1)> doc;
JsonError err = deserializeJson(arr, vla); JsonError err = deserializeJson(doc, vla);
REQUIRE(err == JsonError::Ok); REQUIRE(err == JsonError::Ok);
} }
@ -33,10 +33,10 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "{\"a\":42}"); strcpy(vla, "{\"a\":42}");
StaticJsonObject<JSON_OBJECT_SIZE(1)> obj; StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
deserializeJson(obj, vla); JsonError error = deserializeJson(doc, vla);
REQUIRE(true == obj.success()); REQUIRE(error == JsonError::Ok);
} }
SECTION("Parse") { SECTION("Parse") {
@ -44,7 +44,7 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "42"); strcpy(vla, "42");
StaticJsonVariant<> variant; StaticJsonDocument<> variant;
deserializeJson(variant, vla); deserializeJson(variant, vla);
REQUIRE(42 == variant.as<int>()); REQUIRE(42 == variant.as<int>());
@ -77,8 +77,9 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonVariant variant; DynamicJsonDocument doc;
deserializeJson(variant, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonVariant variant = doc.as<JsonVariant>();
REQUIRE(std::string("world") == variant[vla]); REQUIRE(std::string("world") == variant[vla]);
} }
@ -90,8 +91,9 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonVariant variant; DynamicJsonDocument doc;
deserializeJson(variant, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
const JsonVariant variant = doc.as<JsonVariant>();
REQUIRE(std::string("world") == variant[vla]); REQUIRE(std::string("world") == variant[vla]);
} }
@ -102,7 +104,7 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonVariant variant; JsonVariant variant;
variant = "hello"; variant = "hello";
REQUIRE((vla == variant)); REQUIRE((vla == variant));
@ -116,7 +118,7 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonVariant variant; JsonVariant variant;
variant = "world"; variant = "world";
REQUIRE((vla != variant)); REQUIRE((vla != variant));
@ -131,7 +133,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj[vla] = "world"; obj[vla] = "world";
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -143,7 +146,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj["hello"] = vla; obj["hello"] = vla;
REQUIRE(std::string("world") == obj["hello"].as<char*>()); REQUIRE(std::string("world") == obj["hello"].as<char*>());
@ -154,7 +158,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj["hello"].set(vla); obj["hello"].set(vla);
REQUIRE(std::string("world") == obj["hello"].as<char*>()); REQUIRE(std::string("world") == obj["hello"].as<char*>());
@ -166,9 +171,10 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(std::string("world") == obj[vla]); REQUIRE(std::string("world") == obj[vla]);
} }
#endif #endif
@ -178,9 +184,10 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(std::string("world") == obj.get<char*>(vla)); REQUIRE(std::string("world") == obj.get<char*>(vla));
} }
@ -189,7 +196,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.set(vla, "world"); obj.set(vla, "world");
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -200,7 +208,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.set("hello", vla); obj.set("hello", vla);
REQUIRE(std::string("world") == obj["hello"]); REQUIRE(std::string("world") == obj["hello"]);
@ -211,7 +220,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.set(vla, vla); obj.set(vla, vla);
REQUIRE(std::string("world") == obj["world"]); REQUIRE(std::string("world") == obj["world"]);
@ -222,9 +232,10 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(true == obj.containsKey(vla)); REQUIRE(true == obj.containsKey(vla));
} }
@ -233,8 +244,9 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":\"world\"}"); deserializeJson(doc, "{\"hello\":\"world\"}");
JsonObject& obj = doc.as<JsonObject>();
obj.remove(vla); obj.remove(vla);
REQUIRE(0 == obj.size()); REQUIRE(0 == obj.size());
@ -245,8 +257,9 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
deserializeJson(obj, "{\"hello\":42}"); deserializeJson(doc, "{\"hello\":42}");
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(true == obj.is<int>(vla)); REQUIRE(true == obj.is<int>(vla));
} }
@ -256,7 +269,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.createNestedArray(vla); obj.createNestedArray(vla);
} }
@ -265,7 +279,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "hello"); strcpy(vla, "hello");
DynamicJsonObject obj; DynamicJsonDocument doc;
JsonObject& obj = doc.to<JsonObject>();
obj.createNestedObject(vla); obj.createNestedObject(vla);
} }
@ -274,7 +289,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add(vla); arr.add(vla);
REQUIRE(std::string("world") == arr[0]); REQUIRE(std::string("world") == arr[0]);
@ -285,7 +301,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add("hello"); arr.add("hello");
arr.set(0, vla); arr.set(0, vla);
@ -297,7 +314,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add("hello"); arr.add("hello");
arr[0].set(vla); arr[0].set(vla);
@ -309,7 +327,8 @@ TEST_CASE("Variable Length Array") {
char vla[i]; char vla[i];
strcpy(vla, "world"); strcpy(vla, "world");
DynamicJsonArray arr; DynamicJsonDocument doc;
JsonArray& arr = doc.to<JsonArray>();
arr.add("hello"); arr.add("hello");
arr[0] = vla; arr[0] = vla;

View File

@ -24,8 +24,6 @@ TEST_CASE("MsgPackError") {
TEST_STRINGIFICATION(Ok); TEST_STRINGIFICATION(Ok);
TEST_STRINGIFICATION(NotSupported); TEST_STRINGIFICATION(NotSupported);
TEST_STRINGIFICATION(NoMemory); TEST_STRINGIFICATION(NoMemory);
TEST_STRINGIFICATION(NotAnArray);
TEST_STRINGIFICATION(NotAnObject);
TEST_STRINGIFICATION(TooDeep); TEST_STRINGIFICATION(TooDeep);
} }
@ -33,8 +31,12 @@ TEST_CASE("MsgPackError") {
TEST_BOOLIFICATION(Ok, false); TEST_BOOLIFICATION(Ok, false);
TEST_BOOLIFICATION(NotSupported, true); TEST_BOOLIFICATION(NotSupported, true);
TEST_BOOLIFICATION(NoMemory, true); TEST_BOOLIFICATION(NoMemory, true);
TEST_BOOLIFICATION(NotAnArray, true);
TEST_BOOLIFICATION(NotAnObject, true);
TEST_BOOLIFICATION(TooDeep, true); TEST_BOOLIFICATION(TooDeep, true);
} }
SECTION("ostream") {
std::stringstream s;
s << MsgPackError::NotSupported;
REQUIRE(s.str() == "NotSupported");
}
} }

View File

@ -7,7 +7,7 @@
static void check(const char* input, MsgPackError expected, static void check(const char* input, MsgPackError expected,
uint8_t nestingLimit = 10) { uint8_t nestingLimit = 10) {
DynamicJsonVariant variant; DynamicJsonDocument variant;
MsgPackError error = deserializeMsgPack(variant, input, nestingLimit); MsgPackError error = deserializeMsgPack(variant, input, nestingLimit);

View File

@ -6,21 +6,14 @@
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("deserializeMsgPack(JsonArray&)") { TEST_CASE("deserializeMsgPack(JsonArray&)") {
DynamicJsonArray array; DynamicJsonDocument doc;
SECTION("not an array") {
const char* input = "\xA0";
MsgPackError error = deserializeMsgPack(array, input);
REQUIRE(error == MsgPackError::NotAnArray);
}
SECTION("fixarray") { SECTION("fixarray") {
SECTION("empty") { SECTION("empty") {
const char* input = "\x90"; const char* input = "\x90";
MsgPackError error = deserializeMsgPack(array, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonArray& array = doc.as<JsonArray>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(array.size() == 0); REQUIRE(array.size() == 0);
@ -29,7 +22,8 @@ TEST_CASE("deserializeMsgPack(JsonArray&)") {
SECTION("two integers") { SECTION("two integers") {
const char* input = "\x92\x01\x02"; const char* input = "\x92\x01\x02";
MsgPackError error = deserializeMsgPack(array, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonArray& array = doc.as<JsonArray>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(array.size() == 2); REQUIRE(array.size() == 2);
@ -42,7 +36,8 @@ TEST_CASE("deserializeMsgPack(JsonArray&)") {
SECTION("empty") { SECTION("empty") {
const char* input = "\xDC\x00\x00"; const char* input = "\xDC\x00\x00";
MsgPackError error = deserializeMsgPack(array, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonArray& array = doc.as<JsonArray>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(array.size() == 0); REQUIRE(array.size() == 0);
@ -51,7 +46,8 @@ TEST_CASE("deserializeMsgPack(JsonArray&)") {
SECTION("two strings") { SECTION("two strings") {
const char* input = "\xDC\x00\x02\xA5hello\xA5world"; const char* input = "\xDC\x00\x02\xA5hello\xA5world";
MsgPackError error = deserializeMsgPack(array, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonArray& array = doc.as<JsonArray>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(array.size() == 2); REQUIRE(array.size() == 2);
@ -64,7 +60,8 @@ TEST_CASE("deserializeMsgPack(JsonArray&)") {
SECTION("empty") { SECTION("empty") {
const char* input = "\xDD\x00\x00\x00\x00"; const char* input = "\xDD\x00\x00\x00\x00";
MsgPackError error = deserializeMsgPack(array, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonArray& array = doc.as<JsonArray>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(array.size() == 0); REQUIRE(array.size() == 0);
@ -74,7 +71,8 @@ TEST_CASE("deserializeMsgPack(JsonArray&)") {
const char* input = const char* input =
"\xDD\x00\x00\x00\x02\xCA\x00\x00\x00\x00\xCA\x40\x48\xF5\xC3"; "\xDD\x00\x00\x00\x02\xCA\x00\x00\x00\x00\xCA\x40\x48\xF5\xC3";
MsgPackError error = deserializeMsgPack(array, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonArray& array = doc.as<JsonArray>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(array.size() == 2); REQUIRE(array.size() == 2);

View File

@ -5,36 +5,32 @@
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <catch.hpp> #include <catch.hpp>
TEST_CASE("deserializeMsgPack(JsonObject&)") { TEST_CASE("deserialize MsgPack object") {
DynamicJsonObject object; DynamicJsonDocument doc;
SECTION("not an object") {
const char* input = "\xA0";
MsgPackError error = deserializeMsgPack(object, input);
REQUIRE(error == MsgPackError::NotAnObject);
}
SECTION("fixmap") { SECTION("fixmap") {
SECTION("empty") { SECTION("empty") {
const char* input = "\x80"; const char* input = "\x80";
MsgPackError error = deserializeMsgPack(object, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(object.size() == 0); REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 0);
} }
SECTION("two integers") { SECTION("two integers") {
const char* input = "\x82\xA3one\x01\xA3two\x02"; const char* input = "\x82\xA3one\x01\xA3two\x02";
MsgPackError error = deserializeMsgPack(object, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(object.size() == 2); REQUIRE(doc.is<JsonObject>());
REQUIRE(object["one"] == 1); REQUIRE(obj.size() == 2);
REQUIRE(object["two"] == 2); REQUIRE(obj["one"] == 1);
REQUIRE(obj["two"] == 2);
} }
} }
@ -42,21 +38,25 @@ TEST_CASE("deserializeMsgPack(JsonObject&)") {
SECTION("empty") { SECTION("empty") {
const char* input = "\xDE\x00\x00"; const char* input = "\xDE\x00\x00";
MsgPackError error = deserializeMsgPack(object, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(object.size() == 0); REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 0);
} }
SECTION("two strings") { SECTION("two strings") {
const char* input = "\xDE\x00\x02\xA1H\xA5hello\xA1W\xA5world"; const char* input = "\xDE\x00\x02\xA1H\xA5hello\xA1W\xA5world";
MsgPackError error = deserializeMsgPack(object, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(object.size() == 2); REQUIRE(doc.is<JsonObject>());
REQUIRE(object["H"] == "hello"); REQUIRE(obj.size() == 2);
REQUIRE(object["W"] == "world"); REQUIRE(obj["H"] == "hello");
REQUIRE(obj["W"] == "world");
} }
} }
@ -64,10 +64,12 @@ TEST_CASE("deserializeMsgPack(JsonObject&)") {
SECTION("empty") { SECTION("empty") {
const char* input = "\xDF\x00\x00\x00\x00"; const char* input = "\xDF\x00\x00\x00\x00";
MsgPackError error = deserializeMsgPack(object, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(object.size() == 0); REQUIRE(doc.is<JsonObject>());
REQUIRE(obj.size() == 0);
} }
SECTION("two floats") { SECTION("two floats") {
@ -75,12 +77,14 @@ TEST_CASE("deserializeMsgPack(JsonObject&)") {
"\xDF\x00\x00\x00\x02\xA4zero\xCA\x00\x00\x00\x00\xA2pi\xCA\x40\x48" "\xDF\x00\x00\x00\x02\xA4zero\xCA\x00\x00\x00\x00\xA2pi\xCA\x40\x48"
"\xF5\xC3"; "\xF5\xC3";
MsgPackError error = deserializeMsgPack(object, input); MsgPackError error = deserializeMsgPack(doc, input);
JsonObject& obj = doc.as<JsonObject>();
REQUIRE(error == MsgPackError::Ok); REQUIRE(error == MsgPackError::Ok);
REQUIRE(object.size() == 2); REQUIRE(doc.is<JsonObject>());
REQUIRE(object["zero"] == 0.0f); REQUIRE(obj.size() == 2);
REQUIRE(object["pi"] == 3.14f); REQUIRE(obj["zero"] == 0.0f);
REQUIRE(obj["pi"] == 3.14f);
} }
} }
} }

View File

@ -9,14 +9,14 @@ static const size_t epsilon = sizeof(void*);
template <size_t Capacity> template <size_t Capacity>
static void check(const char* input, MsgPackError expected) { static void check(const char* input, MsgPackError expected) {
StaticJsonVariant<Capacity> variant; StaticJsonDocument<Capacity> variant;
MsgPackError error = deserializeMsgPack(variant, input); MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == expected); REQUIRE(error == expected);
} }
TEST_CASE("deserializeMsgPack(StaticJsonVariant&)") { TEST_CASE("deserializeMsgPack(StaticJsonDocument&)") {
SECTION("single values always fit") { SECTION("single values always fit") {
check<0>("\xc0", MsgPackError::Ok); // nil check<0>("\xc0", MsgPackError::Ok); // nil
check<0>("\xc2", MsgPackError::Ok); // false check<0>("\xc2", MsgPackError::Ok); // false
@ -82,15 +82,14 @@ TEST_CASE("deserializeMsgPack(StaticJsonVariant&)") {
check<JSON_OBJECT_SIZE(0)>("\x80", MsgPackError::Ok); check<JSON_OBJECT_SIZE(0)>("\x80", MsgPackError::Ok);
} }
SECTION("{H:1}") { SECTION("{H:1}") {
check<JSON_OBJECT_SIZE(0)>("\x81\xA1H\x01", check<JSON_OBJECT_SIZE(0)>("\x81\xA1H\x01", MsgPackError::NoMemory);
MsgPackError::NoMemory);
check<JSON_OBJECT_SIZE(1) + epsilon>("\x81\xA1H\x01", MsgPackError::Ok); check<JSON_OBJECT_SIZE(1) + epsilon>("\x81\xA1H\x01", MsgPackError::Ok);
} }
SECTION("{H:1,W:2}") { SECTION("{H:1,W:2}") {
check<JSON_OBJECT_SIZE(1) + epsilon>("\x82\xA1H\x01\xA1W\x02", check<JSON_OBJECT_SIZE(1) + epsilon>("\x82\xA1H\x01\xA1W\x02",
MsgPackError::NoMemory); MsgPackError::NoMemory);
check<JSON_OBJECT_SIZE(2) + 2*epsilon>("\x82\xA1H\x01\xA1W\x02", check<JSON_OBJECT_SIZE(2) + 2 * epsilon>("\x82\xA1H\x01\xA1W\x02",
MsgPackError::Ok); MsgPackError::Ok);
} }
} }
@ -101,13 +100,14 @@ TEST_CASE("deserializeMsgPack(StaticJsonVariant&)") {
SECTION("{H:1}") { SECTION("{H:1}") {
check<JSON_OBJECT_SIZE(0)>("\xDE\x00\x01\xA1H\x01", check<JSON_OBJECT_SIZE(0)>("\xDE\x00\x01\xA1H\x01",
MsgPackError::NoMemory); MsgPackError::NoMemory);
check<JSON_OBJECT_SIZE(1) + epsilon>("\xDE\x00\x01\xA1H\x01", MsgPackError::Ok); check<JSON_OBJECT_SIZE(1) + epsilon>("\xDE\x00\x01\xA1H\x01",
MsgPackError::Ok);
} }
SECTION("{H:1,W:2}") { SECTION("{H:1,W:2}") {
check<JSON_OBJECT_SIZE(1) + epsilon>("\xDE\x00\x02\xA1H\x01\xA1W\x02", check<JSON_OBJECT_SIZE(1) + epsilon>("\xDE\x00\x02\xA1H\x01\xA1W\x02",
MsgPackError::NoMemory); MsgPackError::NoMemory);
check<JSON_OBJECT_SIZE(2) + 2*epsilon>("\xDE\x00\x02\xA1H\x01\xA1W\x02", check<JSON_OBJECT_SIZE(2) + 2 * epsilon>("\xDE\x00\x02\xA1H\x01\xA1W\x02",
MsgPackError::Ok); MsgPackError::Ok);
} }
} }
@ -119,13 +119,13 @@ TEST_CASE("deserializeMsgPack(StaticJsonVariant&)") {
check<JSON_OBJECT_SIZE(0)>("\xDF\x00\x00\x00\x01\xA1H\x01", check<JSON_OBJECT_SIZE(0)>("\xDF\x00\x00\x00\x01\xA1H\x01",
MsgPackError::NoMemory); MsgPackError::NoMemory);
check<JSON_OBJECT_SIZE(1) + epsilon>("\xDF\x00\x00\x00\x01\xA1H\x01", check<JSON_OBJECT_SIZE(1) + epsilon>("\xDF\x00\x00\x00\x01\xA1H\x01",
MsgPackError::Ok); MsgPackError::Ok);
} }
SECTION("{H:1,W:2}") { SECTION("{H:1,W:2}") {
check<JSON_OBJECT_SIZE(1) + epsilon>("\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02", check<JSON_OBJECT_SIZE(1) + epsilon>(
MsgPackError::NoMemory); "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02", MsgPackError::NoMemory);
check<JSON_OBJECT_SIZE(2) + 2*epsilon>("\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02", check<JSON_OBJECT_SIZE(2) + 2 * epsilon>(
MsgPackError::Ok); "\xDF\x00\x00\x00\x02\xA1H\x01\xA1W\x02", MsgPackError::Ok);
} }
} }
} }

View File

@ -7,7 +7,7 @@
template <typename T, typename U> template <typename T, typename U>
static void check(const char* input, U expected) { static void check(const char* input, U expected) {
DynamicJsonVariant variant; DynamicJsonDocument variant;
MsgPackError error = deserializeMsgPack(variant, input); MsgPackError error = deserializeMsgPack(variant, input);
@ -127,151 +127,4 @@ TEST_CASE("deserializeMsgPack(JsonVariant&)") {
SECTION("str 32") { SECTION("str 32") {
check<const char*>("\xdb\x00\x00\x00\x05hello", std::string("hello")); check<const char*>("\xdb\x00\x00\x00\x05hello", std::string("hello"));
} }
SECTION("fixarray") {
DynamicJsonVariant variant;
SECTION("empty") {
const char* input = "\x90";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 0);
}
SECTION("two integers") {
const char* input = "\x92\x01\x02";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 2);
REQUIRE(variant[0] == 1);
REQUIRE(variant[1] == 2);
}
}
SECTION("array 16") {
DynamicJsonVariant variant;
SECTION("empty") {
const char* input = "\xDC\x00\x00";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 0);
}
SECTION("two strings") {
const char* input = "\xDC\x00\x02\xA5hello\xA5world";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 2);
REQUIRE(variant[0] == "hello");
REQUIRE(variant[1] == "world");
}
}
SECTION("array 32") {
DynamicJsonVariant variant;
SECTION("empty") {
const char* input = "\xDD\x00\x00\x00\x00";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 0);
}
SECTION("two floats") {
const char* input =
"\xDD\x00\x00\x00\x02\xCA\x00\x00\x00\x00\xCA\x40\x48\xF5\xC3";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 2);
REQUIRE(variant[0] == 0.0f);
REQUIRE(variant[1] == 3.14f);
}
}
SECTION("fixmap") {
DynamicJsonVariant variant;
SECTION("empty") {
const char* input = "\x80";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 0);
}
SECTION("two integers") {
const char* input = "\x82\xA3one\x01\xA3two\x02";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 2);
REQUIRE(variant["one"] == 1);
REQUIRE(variant["two"] == 2);
}
}
SECTION("map 16") {
DynamicJsonVariant variant;
SECTION("empty") {
const char* input = "\xDE\x00\x00";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 0);
}
SECTION("two strings") {
const char* input = "\xDE\x00\x02\xA1H\xA5hello\xA1W\xA5world";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 2);
REQUIRE(variant["H"] == "hello");
REQUIRE(variant["W"] == "world");
}
}
SECTION("map 32") {
DynamicJsonVariant variant;
SECTION("empty") {
const char* input = "\xDF\x00\x00\x00\x00";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 0);
}
SECTION("two floats") {
const char* input =
"\xDF\x00\x00\x00\x02\xA4zero\xCA\x00\x00\x00\x00\xA2pi\xCA\x40\x48"
"\xF5\xC3";
MsgPackError error = deserializeMsgPack(variant, input);
REQUIRE(error == MsgPackError::Ok);
REQUIRE(variant.size() == 2);
REQUIRE(variant["zero"] == 0.0f);
REQUIRE(variant["pi"] == 3.14f);
}
}
} }

View File

@ -2,9 +2,11 @@
// Copyright Benoit Blanchon 2014-2018 // Copyright Benoit Blanchon 2014-2018
// MIT License // MIT License
#include <ArduinoJson.h> #include <ArduinoJson/Memory/StaticJsonBuffer.hpp>
#include <catch.hpp> #include <catch.hpp>
using namespace ArduinoJson::Internals;
static bool isAligned(void *ptr) { static bool isAligned(void *ptr) {
const size_t mask = sizeof(void *) - 1; const size_t mask = sizeof(void *) - 1;
size_t addr = reinterpret_cast<size_t>(ptr); size_t addr = reinterpret_cast<size_t>(ptr);

View File

@ -2,9 +2,11 @@
// Copyright Benoit Blanchon 2014-2018 // Copyright Benoit Blanchon 2014-2018
// MIT License // MIT License
#include <ArduinoJson.h> #include <ArduinoJson/Memory/StaticJsonBuffer.hpp>
#include <catch.hpp> #include <catch.hpp>
using namespace ArduinoJson::Internals;
TEST_CASE("StaticJsonBuffer::size()") { TEST_CASE("StaticJsonBuffer::size()") {
StaticJsonBuffer<64> buffer; StaticJsonBuffer<64> buffer;