mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-16 12:02:14 +02:00
JsonVariant automatically promotes to JsonObject or JsonArray on write
This commit is contained in:
@ -22,6 +22,12 @@ HEAD
|
|||||||
* Added `JsonDocument::operator[]`
|
* Added `JsonDocument::operator[]`
|
||||||
* Added `ARDUINOJSON_TAB` to configure the indentation character
|
* Added `ARDUINOJSON_TAB` to configure the indentation character
|
||||||
* Reduced the size of the pretty JSON serializer
|
* Reduced the size of the pretty JSON serializer
|
||||||
|
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
|
||||||
|
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
|
||||||
|
Calling `JsonVariant::to<T>()` is not required anymore.
|
||||||
|
* `JsonDocument` now support the same operations as `JsonVariant`.
|
||||||
|
Calling `JsonDocument::as<T>()` is not required anymore.
|
||||||
|
* Fixed example `JsonHttpClient.ino`
|
||||||
|
|
||||||
> ### BREAKING CHANGES
|
> ### BREAKING CHANGES
|
||||||
>
|
>
|
||||||
|
@ -15,7 +15,11 @@
|
|||||||
#include <SD.h>
|
#include <SD.h>
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
|
|
||||||
// Configuration that we'll store on disk
|
// Our configuration structure.
|
||||||
|
//
|
||||||
|
// Never use a JsonDocument to store the configuration!
|
||||||
|
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
|
||||||
|
// used during the serialization phase.
|
||||||
struct Config {
|
struct Config {
|
||||||
char hostname[64];
|
char hostname[64];
|
||||||
int port;
|
int port;
|
||||||
@ -29,9 +33,9 @@ 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 document on the stack.
|
// Allocate a temporary JsonDocument
|
||||||
// Don't forget to change the capacity to match your requirements.
|
// Don't forget to change the capacity to match your requirements.
|
||||||
// Use arduinojson.org/assistant to compute the capacity.
|
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||||
StaticJsonDocument<512> doc;
|
StaticJsonDocument<512> doc;
|
||||||
|
|
||||||
// Deserialize the JSON document
|
// Deserialize the JSON document
|
||||||
@ -39,16 +43,13 @@ void loadConfiguration(const char *filename, Config &config) {
|
|||||||
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
|
// Copy values from the JsonDocument to the Config
|
||||||
JsonObject root = doc.as<JsonObject>();
|
config.port = doc["port"] | 2731;
|
||||||
|
|
||||||
// Copy values from the JsonObject to the Config
|
|
||||||
config.port = root["port"] | 2731;
|
|
||||||
strlcpy(config.hostname, // <- destination
|
strlcpy(config.hostname, // <- destination
|
||||||
root["hostname"] | "example.com", // <- source
|
doc["hostname"] | "example.com", // <- source
|
||||||
sizeof(config.hostname)); // <- destination's capacity
|
sizeof(config.hostname)); // <- destination's capacity
|
||||||
|
|
||||||
// Close the file (File's destructor doesn't close the file)
|
// Close the file (Curiously, File's destructor doesn't close the file)
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,24 +65,21 @@ void saveConfiguration(const char *filename, const Config &config) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the document on the stack.
|
// Allocate a temporary JsonDocument
|
||||||
// Don't forget to change the capacity to match your requirements.
|
// 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.
|
||||||
StaticJsonDocument<256> doc;
|
StaticJsonDocument<256> doc;
|
||||||
|
|
||||||
// Make our document contain an object
|
// Set the values in the document
|
||||||
JsonObject root = doc.to<JsonObject>();
|
doc["hostname"] = config.hostname;
|
||||||
|
doc["port"] = config.port;
|
||||||
// Set the values in the object
|
|
||||||
root["hostname"] = config.hostname;
|
|
||||||
root["port"] = config.port;
|
|
||||||
|
|
||||||
// Serialize JSON to file
|
// Serialize JSON to file
|
||||||
if (serializeJson(doc, file) == 0) {
|
if (serializeJson(doc, file) == 0) {
|
||||||
Serial.println(F("Failed to write to file"));
|
Serial.println(F("Failed to write to file"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the file (File's destructor doesn't close the file)
|
// Close the file
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +98,7 @@ void printFile(const char *filename) {
|
|||||||
}
|
}
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
// Close the file (File's destructor doesn't close the file)
|
// Close the file
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ void setup() {
|
|||||||
//
|
//
|
||||||
// Inside the brackets, 200 is the RAM allocated to this document.
|
// Inside the brackets, 200 is the RAM allocated to this document.
|
||||||
// Don't forget to change this value to match your requirement.
|
// Don't forget to change this value to match your requirement.
|
||||||
// Use arduinojson.org/assistant to compute the capacity.
|
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||||
StaticJsonDocument<200> doc;
|
StaticJsonDocument<200> doc;
|
||||||
|
|
||||||
// StaticJsonObject allocates memory on the stack, it can be
|
// StaticJsonObject allocates memory on the stack, it can be
|
||||||
@ -23,30 +23,30 @@ void setup() {
|
|||||||
//
|
//
|
||||||
// DynamicJsonDocument doc(200);
|
// DynamicJsonDocument doc(200);
|
||||||
|
|
||||||
// Make our document be an object
|
// Add values in the document
|
||||||
JsonObject root = doc.to<JsonObject>();
|
|
||||||
|
|
||||||
// Add values in the object
|
|
||||||
//
|
//
|
||||||
// Most of the time, you can rely on the implicit casts.
|
doc["sensor"] = "gps";
|
||||||
// In other case, you can do root.set<long>("time", 1351824120);
|
doc["time"] = 1351824120;
|
||||||
root["sensor"] = "gps";
|
|
||||||
root["time"] = 1351824120;
|
|
||||||
|
|
||||||
// Add an array.
|
// Add an array.
|
||||||
//
|
//
|
||||||
JsonArray data = root.createNestedArray("data");
|
JsonArray data = doc.createNestedArray("data");
|
||||||
data.add(48.756080);
|
data.add(48.756080);
|
||||||
data.add(2.302038);
|
data.add(2.302038);
|
||||||
|
|
||||||
|
// Generate the minified JSON and send it to the Serial port.
|
||||||
|
//
|
||||||
serializeJson(doc, Serial);
|
serializeJson(doc, Serial);
|
||||||
// This prints:
|
// The above line prints:
|
||||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
|
|
||||||
|
// Start a new line
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
|
// Generate the prettified JSON and send it to the Serial port.
|
||||||
|
//
|
||||||
serializeJsonPretty(doc, Serial);
|
serializeJsonPretty(doc, Serial);
|
||||||
// This prints:
|
// The above line prints:
|
||||||
// {
|
// {
|
||||||
// "sensor": "gps",
|
// "sensor": "gps",
|
||||||
// "time": 1351824120,
|
// "time": 1351824120,
|
||||||
|
@ -71,7 +71,7 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the JSON document
|
// Allocate the JSON document
|
||||||
// Use arduinojson.org/assistant to compute the capacity.
|
// Use arduinojson.org/v6/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;
|
||||||
DynamicJsonDocument doc(capacity);
|
DynamicJsonDocument doc(capacity);
|
||||||
|
|
||||||
@ -84,12 +84,11 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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(doc["sensor"].as<char*>());
|
||||||
Serial.println(root["time"].as<char*>());
|
Serial.println(doc["time"].as<long>());
|
||||||
Serial.println(root["data"][0].as<char*>());
|
Serial.println(doc["data"][0].as<float>(), 6);
|
||||||
Serial.println(root["data"][1].as<char*>());
|
Serial.println(doc["data"][1].as<float>(), 6);
|
||||||
|
|
||||||
// Disconnect
|
// Disconnect
|
||||||
client.stop();
|
client.stop();
|
||||||
|
@ -13,9 +13,9 @@ void setup() {
|
|||||||
|
|
||||||
// Allocate the JSON document
|
// Allocate the JSON document
|
||||||
//
|
//
|
||||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
// Inside the brackets, 200 is the capacity 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/v6/assistant to compute the capacity.
|
||||||
StaticJsonDocument<200> doc;
|
StaticJsonDocument<200> doc;
|
||||||
|
|
||||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||||
@ -25,9 +25,12 @@ void setup() {
|
|||||||
|
|
||||||
// JSON input string.
|
// JSON input string.
|
||||||
//
|
//
|
||||||
// It's better to use a char[] as shown here.
|
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
|
||||||
// If you use a const char* or a String, ArduinoJson will
|
// the minimal amount of memory because the JsonDocument stores pointers to
|
||||||
// have to make a copy of the input in the JsonBuffer.
|
// the input buffer.
|
||||||
|
// If you use another type of input, ArduinoJson must copy the strings from
|
||||||
|
// the input to the JsonDocument, so you need to increase the capacity of the
|
||||||
|
// JsonDocument.
|
||||||
char json[] =
|
char json[] =
|
||||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||||
|
|
||||||
@ -41,17 +44,14 @@ void setup() {
|
|||||||
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 = doc["sensor"];
|
||||||
long time = root["time"];
|
long time = doc["time"];
|
||||||
double latitude = root["data"][0];
|
double latitude = doc["data"][0];
|
||||||
double longitude = root["data"][1];
|
double longitude = doc["data"][1];
|
||||||
|
|
||||||
// Print values.
|
// Print values.
|
||||||
Serial.println(sensor);
|
Serial.println(sensor);
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
// Copyright Benoit Blanchon 2014-2018
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
// MIT License
|
// MIT License
|
||||||
//
|
//
|
||||||
// This example shows how to implement an HTTP server that sends JSON document
|
// This example shows how to implement an HTTP server that sends a JSON document
|
||||||
// in the responses.
|
// in the response.
|
||||||
// It uses the Ethernet library but can be easily adapted for Wifi.
|
// It uses the Ethernet library but can be easily adapted for Wifi.
|
||||||
//
|
//
|
||||||
// It sends the value of the analog and digital pins.
|
// The JSON document contains the values of the analog and digital pins.
|
||||||
// The JSON document looks like the following:
|
// It looks like that:
|
||||||
// {
|
// {
|
||||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
// "analog": [0, 76, 123, 158, 192, 205],
|
||||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
@ -51,15 +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 JSON document
|
// Allocate a temporary JsonDocument
|
||||||
// Use arduinojson.org/assistant to compute the capacity.
|
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||||
StaticJsonDocument<500> doc;
|
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 = doc.createNestedArray("analog");
|
||||||
for (int pin = 0; pin < 6; pin++) {
|
for (int pin = 0; pin < 6; pin++) {
|
||||||
// Read the analog input
|
// Read the analog input
|
||||||
int value = analogRead(pin);
|
int value = analogRead(pin);
|
||||||
@ -69,7 +66,7 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the "digital" array
|
// Create the "digital" array
|
||||||
JsonArray digitalValues = root.createNestedArray("digital");
|
JsonArray digitalValues = doc.createNestedArray("digital");
|
||||||
for (int pin = 0; pin < 14; pin++) {
|
for (int pin = 0; pin < 14; pin++) {
|
||||||
// Read the digital input
|
// Read the digital input
|
||||||
int value = digitalRead(pin);
|
int value = digitalRead(pin);
|
||||||
@ -83,9 +80,11 @@ void loop() {
|
|||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
// Write response headers
|
// Write response headers
|
||||||
client.println("HTTP/1.0 200 OK");
|
client.println(F("HTTP/1.0 200 OK"));
|
||||||
client.println("Content-Type: application/json");
|
client.println(F("Content-Type: application/json"));
|
||||||
client.println("Connection: close");
|
client.println(F("Connection: close"));
|
||||||
|
client.print(F("Content-Length: "));
|
||||||
|
client.println(measureJsonPretty(doc));
|
||||||
client.println();
|
client.println();
|
||||||
|
|
||||||
// Write JSON document
|
// Write JSON document
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
// This example shows how to send a JSON document to a UDP socket.
|
// This example shows how to send a JSON document to a UDP socket.
|
||||||
// At regular interval, it sends a UDP packet that contains the status of
|
// At regular interval, it sends a UDP packet that contains the status of
|
||||||
// analog and digital pins.
|
// analog and digital pins.
|
||||||
// The JSON document looks like the following:
|
// It looks like that:
|
||||||
// {
|
// {
|
||||||
// "analog": [ 0, 1, 2, 3, 4, 5 ],
|
// "analog": [0, 76, 123, 158, 192, 205],
|
||||||
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
|
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// If you want to test this program, you need to be able to receive the UDP
|
// If you want to test this program, you need to be able to receive the UDP
|
||||||
@ -43,15 +43,12 @@ void setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// Allocate the JSON document
|
// Allocate a temporary JsonDocument
|
||||||
// Use arduinojson.org/assistant to compute the capacity.
|
// Use arduinojson.org/v6/assistant to compute the capacity.
|
||||||
StaticJsonDocument<500> doc;
|
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 = doc.createNestedArray("analog");
|
||||||
for (int pin = 0; pin < 6; pin++) {
|
for (int pin = 0; pin < 6; pin++) {
|
||||||
// Read the analog input
|
// Read the analog input
|
||||||
int value = analogRead(pin);
|
int value = analogRead(pin);
|
||||||
@ -61,7 +58,7 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the "digital" array
|
// Create the "digital" array
|
||||||
JsonArray digitalValues = root.createNestedArray("digital");
|
JsonArray digitalValues = doc.createNestedArray("digital");
|
||||||
for (int pin = 0; pin < 14; pin++) {
|
for (int pin = 0; pin < 14; pin++) {
|
||||||
// Read the digital input
|
// Read the digital input
|
||||||
int value = digitalRead(pin);
|
int value = digitalRead(pin);
|
||||||
|
@ -14,9 +14,9 @@ void setup() {
|
|||||||
|
|
||||||
// Allocate the JSON document
|
// Allocate the JSON document
|
||||||
//
|
//
|
||||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
// Inside the brackets, 200 is the capacity 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/v6/assistant to compute the capacity.
|
||||||
StaticJsonDocument<200> doc;
|
StaticJsonDocument<200> doc;
|
||||||
|
|
||||||
// StaticJsonObject allocates memory on the stack, it can be
|
// StaticJsonObject allocates memory on the stack, it can be
|
||||||
@ -26,9 +26,12 @@ void setup() {
|
|||||||
|
|
||||||
// MessagePack input string.
|
// MessagePack input string.
|
||||||
//
|
//
|
||||||
// It's better to use a char[] as shown here.
|
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
|
||||||
// If you use a const char* or a String, ArduinoJson will
|
// the minimal amount of memory because the JsonDocument stores pointers to
|
||||||
// have to make a copy of the input in the JsonBuffer.
|
// the input buffer.
|
||||||
|
// If you use another type of input, ArduinoJson must copy the strings from
|
||||||
|
// the input to the JsonDocument, so you need to increase the capacity of the
|
||||||
|
// JsonDocument.
|
||||||
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
|
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
|
||||||
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
|
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
|
||||||
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
|
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
|
||||||
@ -40,31 +43,23 @@ void setup() {
|
|||||||
// "data": [48.75608, 2.302038]
|
// "data": [48.75608, 2.302038]
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// doc of the object tree.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
DeserializationError error = deserializeMsgPack(doc, input);
|
DeserializationError error = deserializeMsgPack(doc, input);
|
||||||
|
|
||||||
// Test if parsing succeeds.
|
// Test if parsing succeeded.
|
||||||
if (error) {
|
if (error) {
|
||||||
Serial.print("deserializeMsgPack() failed: ");
|
Serial.print("deserializeMsgPack() failed: ");
|
||||||
Serial.println(error.c_str());
|
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 = doc["sensor"];
|
||||||
long time = root["time"];
|
long time = doc["time"];
|
||||||
double latitude = root["data"][0];
|
double latitude = doc["data"][0];
|
||||||
double longitude = root["data"][1];
|
double longitude = doc["data"][1];
|
||||||
|
|
||||||
// Print values.
|
// Print values.
|
||||||
Serial.println(sensor);
|
Serial.println(sensor);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
// ArduinoJson.
|
// ArduinoJson.
|
||||||
//
|
//
|
||||||
// Use Flash strings sparingly, because ArduinoJson duplicates them in the
|
// Use Flash strings sparingly, because ArduinoJson duplicates them in the
|
||||||
// JsonBuffer. Prefer plain old char*, as they are more efficient in term of
|
// JsonDocument. Prefer plain old char*, as they are more efficient in term of
|
||||||
// code size, speed, and memory usage.
|
// code size, speed, and memory usage.
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
@ -17,8 +17,7 @@ void setup() {
|
|||||||
DynamicJsonDocument doc(1024);
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
// 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 string in the input will be duplicated in the JsonDocument.
|
||||||
// JsonBuffer.
|
|
||||||
deserializeJson(doc, 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>();
|
JsonObject obj = doc.as<JsonObject>();
|
||||||
@ -29,12 +28,12 @@ void setup() {
|
|||||||
|
|
||||||
// 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.
|
// JsonDocument.
|
||||||
obj[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.
|
// JsonDocument.
|
||||||
obj["sensor"] = F("gps");
|
obj["sensor"] = F("gps");
|
||||||
|
|
||||||
// It works with serialized() too:
|
// It works with serialized() too:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// This example shows the different ways you can use String with ArduinoJson.
|
// This example shows the different ways you can use String with ArduinoJson.
|
||||||
//
|
//
|
||||||
// Use String objects sparingly, because ArduinoJson duplicates them in the
|
// Use String objects sparingly, because ArduinoJson duplicates them in the
|
||||||
// JsonBuffer. Prefer plain old char[], as they are more efficient in term of
|
// JsonDocument. Prefer plain old char[], as they are more efficient in term of
|
||||||
// code size, speed, and memory usage.
|
// code size, speed, and memory usage.
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
@ -14,7 +14,7 @@ void setup() {
|
|||||||
DynamicJsonDocument doc(1024);
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
// 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 string in the input will be duplicated in the JsonDocument.
|
||||||
String input =
|
String input =
|
||||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||||
deserializeJson(doc, input);
|
deserializeJson(doc, input);
|
||||||
@ -25,11 +25,11 @@ void setup() {
|
|||||||
long time = obj[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 JsonDocument.
|
||||||
obj[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 JsonDocument.
|
||||||
String sensor = obj["sensor"];
|
String sensor = obj["sensor"];
|
||||||
|
|
||||||
// Unfortunately, the following doesn't work (issue #118):
|
// Unfortunately, the following doesn't work (issue #118):
|
||||||
@ -38,14 +38,14 @@ void setup() {
|
|||||||
sensor = obj["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 JsonDocument.
|
||||||
obj["sensor"] = sensor;
|
obj["sensor"] = sensor;
|
||||||
|
|
||||||
// It works with serialized() too:
|
// It works with serialized() too:
|
||||||
obj["sensor"] = serialized(sensor);
|
obj["sensor"] = serialized(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 JsonDocument.
|
||||||
obj[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
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
|
||||||
|
|
||||||
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
#include "ArduinoJson/Array/ArrayImpl.hpp"
|
||||||
#include "ArduinoJson/Array/ArraySubscript.hpp"
|
#include "ArduinoJson/Array/ElementProxy.hpp"
|
||||||
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
#include "ArduinoJson/Collection/CollectionImpl.hpp"
|
||||||
|
#include "ArduinoJson/Object/MemberProxy.hpp"
|
||||||
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
#include "ArduinoJson/Object/ObjectImpl.hpp"
|
||||||
#include "ArduinoJson/Object/ObjectSubscript.hpp"
|
|
||||||
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
|
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
|
||||||
#include "ArduinoJson/Variant/VariantImpl.hpp"
|
#include "ArduinoJson/Variant/VariantImpl.hpp"
|
||||||
|
|
||||||
|
@ -9,11 +9,14 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
inline ArrayRef ArrayRef::createNestedArray() const {
|
template <typename TArray>
|
||||||
return add().to<ArrayRef>();
|
inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
|
||||||
|
return impl()->add().template to<ArrayRef>();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ObjectRef ArrayRef::createNestedObject() const {
|
template <typename TArray>
|
||||||
return add().to<ObjectRef>();
|
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
|
||||||
|
return impl()->add().template to<ObjectRef>();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -16,11 +16,16 @@
|
|||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
class ObjectRef;
|
class ObjectRef;
|
||||||
class ArraySubscript;
|
template <typename>
|
||||||
|
class ElementProxy;
|
||||||
|
|
||||||
template <typename TData>
|
template <typename TData>
|
||||||
class ArrayRefBase {
|
class ArrayRefBase {
|
||||||
public:
|
public:
|
||||||
|
operator VariantConstRef() const {
|
||||||
|
return VariantConstRef(reinterpret_cast<const VariantData*>(_data));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||||
arrayAccept(_data, visitor);
|
arrayAccept(_data, visitor);
|
||||||
@ -30,10 +35,6 @@ class ArrayRefBase {
|
|||||||
return _data == 0;
|
return _data == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
|
||||||
return VariantConstRef(_data ? _data->get(index) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
return _data ? _data->memoryUsage() : 0;
|
return _data ? _data->memoryUsage() : 0;
|
||||||
}
|
}
|
||||||
@ -74,9 +75,15 @@ class ArrayConstRef : public ArrayRefBase<const CollectionData>,
|
|||||||
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
|
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
|
||||||
return arrayEquals(_data, rhs._data);
|
return arrayEquals(_data, rhs._data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
||||||
|
return VariantConstRef(_data ? _data->get(index) : 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
|
class ArrayRef : public ArrayRefBase<CollectionData>,
|
||||||
|
public ArrayShortcuts<ArrayRef>,
|
||||||
|
public Visitable {
|
||||||
typedef ArrayRefBase<CollectionData> base_type;
|
typedef ArrayRefBase<CollectionData> base_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -94,27 +101,7 @@ class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
|
|||||||
return ArrayConstRef(_data);
|
return ArrayConstRef(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds the specified value at the end of the array.
|
using ArrayShortcuts::add;
|
||||||
//
|
|
||||||
// bool add(TValue);
|
|
||||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
|
||||||
// std::string, String, ObjectRef
|
|
||||||
template <typename T>
|
|
||||||
FORCE_INLINE bool add(const T& value) const {
|
|
||||||
return add().set(value);
|
|
||||||
}
|
|
||||||
// Adds the specified value at the end of the array.
|
|
||||||
FORCE_INLINE bool add(ArrayConstRef value) const {
|
|
||||||
return add().set(value);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// bool add(TValue);
|
|
||||||
// TValue = char*, const char*, const __FlashStringHelper*
|
|
||||||
template <typename T>
|
|
||||||
FORCE_INLINE bool add(T* value) const {
|
|
||||||
return add().set(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
VariantRef add() const {
|
VariantRef add() const {
|
||||||
return VariantRef(_pool, arrayAdd(_data, _pool));
|
return VariantRef(_pool, arrayAdd(_data, _pool));
|
||||||
}
|
}
|
||||||
@ -187,11 +174,6 @@ class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE ArrayRef createNestedArray() const;
|
|
||||||
FORCE_INLINE ObjectRef createNestedObject() const;
|
|
||||||
|
|
||||||
FORCE_INLINE ArraySubscript operator[](size_t index) const;
|
|
||||||
|
|
||||||
FORCE_INLINE bool operator==(ArrayRef rhs) const {
|
FORCE_INLINE bool operator==(ArrayRef rhs) const {
|
||||||
return arrayEquals(_data, rhs._data);
|
return arrayEquals(_data, rhs._data);
|
||||||
}
|
}
|
||||||
|
47
src/ArduinoJson/Array/ArrayShortcuts.hpp
Normal file
47
src/ArduinoJson/Array/ArrayShortcuts.hpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Polyfills/attributes.hpp"
|
||||||
|
#include "../Polyfills/type_traits.hpp"
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
// Forward declarations.
|
||||||
|
template <typename>
|
||||||
|
class ElementProxy;
|
||||||
|
|
||||||
|
template <typename TArray>
|
||||||
|
class ArrayShortcuts {
|
||||||
|
public:
|
||||||
|
// Returns the element at specified index if the variant is an array.
|
||||||
|
FORCE_INLINE ElementProxy<const TArray &> operator[](size_t index) const;
|
||||||
|
|
||||||
|
FORCE_INLINE ObjectRef createNestedObject() const;
|
||||||
|
|
||||||
|
FORCE_INLINE ArrayRef createNestedArray() const;
|
||||||
|
|
||||||
|
// Adds the specified value at the end of the array.
|
||||||
|
//
|
||||||
|
// bool add(TValue);
|
||||||
|
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||||
|
// std::string, String, ObjectRef
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE bool add(const T &value) const {
|
||||||
|
return impl()->add().set(value);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool add(TValue);
|
||||||
|
// TValue = char*, const char*, const __FlashStringHelper*
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE bool add(T *value) const {
|
||||||
|
return impl()->add().set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const TArray *impl() const {
|
||||||
|
return static_cast<const TArray *>(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -13,14 +13,18 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
class ArraySubscript : public VariantOperators<ArraySubscript>,
|
|
||||||
|
template <typename TArray>
|
||||||
|
class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||||
public Visitable {
|
public Visitable {
|
||||||
|
typedef ElementProxy<TArray> this_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FORCE_INLINE ArraySubscript(ArrayRef array, size_t index)
|
FORCE_INLINE ElementProxy(TArray array, size_t index)
|
||||||
: _array(array), _index(index) {}
|
: _array(array), _index(index) {}
|
||||||
|
|
||||||
FORCE_INLINE ArraySubscript& operator=(const ArraySubscript& src) {
|
FORCE_INLINE this_type& operator=(const this_type& src) {
|
||||||
get_impl().set(src.as<VariantConstRef>());
|
getElement().set(src.as<VariantConstRef>());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,36 +34,36 @@ class ArraySubscript : public VariantOperators<ArraySubscript>,
|
|||||||
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||||
// std::string, String, ArrayRef, ObjectRef
|
// std::string, String, ArrayRef, ObjectRef
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE ArraySubscript& operator=(const T& src) {
|
FORCE_INLINE this_type& operator=(const T& src) {
|
||||||
get_impl().set(src);
|
getElement().set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// operator=(TValue)
|
// operator=(TValue)
|
||||||
// TValue = char*, const char*, const __FlashStringHelper*
|
// TValue = char*, const char*, const __FlashStringHelper*
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE ArraySubscript& operator=(T* src) {
|
FORCE_INLINE this_type& operator=(T* src) {
|
||||||
get_impl().set(src);
|
getElement().set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return get_impl().isNull();
|
return getElement().isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE typename VariantAs<T>::type as() const {
|
FORCE_INLINE typename VariantAs<T>::type as() const {
|
||||||
return get_impl().as<T>();
|
return getElement().template as<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE bool is() const {
|
FORCE_INLINE bool is() const {
|
||||||
return get_impl().is<T>();
|
return getElement().template is<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
FORCE_INLINE typename VariantTo<T>::type to() const {
|
FORCE_INLINE typename VariantTo<T>::type to() const {
|
||||||
return get_impl().to<T>();
|
return getElement().template to<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces the value
|
// Replaces the value
|
||||||
@ -69,42 +73,65 @@ class ArraySubscript : public VariantOperators<ArraySubscript>,
|
|||||||
// std::string, String, ArrayRef, ObjectRef
|
// std::string, String, ArrayRef, ObjectRef
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(const TValue& value) const {
|
FORCE_INLINE bool set(const TValue& value) const {
|
||||||
return get_impl().set(value);
|
return getElement().set(value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TValue)
|
// bool set(TValue)
|
||||||
// TValue = char*, const char*, const __FlashStringHelper*
|
// TValue = char*, const char*, const __FlashStringHelper*
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(TValue* value) const {
|
FORCE_INLINE bool set(TValue* value) const {
|
||||||
return get_impl().set(value);
|
return getElement().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
void accept(Visitor& visitor) const {
|
void accept(Visitor& visitor) const {
|
||||||
return get_impl().accept(visitor);
|
return getElement().accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return get_impl().size();
|
return getElement().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
VariantRef get(TNestedKey* key) const {
|
||||||
|
return getElement().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
VariantRef get(const TNestedKey& key) const {
|
||||||
|
return getElement().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
VariantRef getOrCreate(TNestedKey* key) const {
|
||||||
|
return getElement().getOrCreate(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
VariantRef getOrCreate(const TNestedKey& key) const {
|
||||||
|
return getElement().getOrCreate(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
using ArrayShortcuts<ElementProxy>::add;
|
||||||
|
VariantRef add() const {
|
||||||
|
return getElement().add();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FORCE_INLINE VariantRef get_impl() const {
|
FORCE_INLINE VariantRef getElement() const {
|
||||||
return _array.get(_index);
|
return _array.get(_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef _array;
|
TArray _array;
|
||||||
const size_t _index;
|
const size_t _index;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TImpl>
|
template <typename TArray>
|
||||||
inline ArraySubscript VariantSubscripts<TImpl>::operator[](size_t index) const {
|
inline ElementProxy<const TArray&> ArrayShortcuts<TArray>::operator[](
|
||||||
return impl()->template as<ArrayRef>()[index];
|
size_t index) const {
|
||||||
|
return ElementProxy<const TArray&>(*impl(), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ArraySubscript ArrayRef::operator[](size_t index) const {
|
|
||||||
return ArraySubscript(*this, index);
|
|
||||||
}
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
@ -9,7 +9,8 @@
|
|||||||
#include "../Variant/VariantRef.hpp"
|
#include "../Variant/VariantRef.hpp"
|
||||||
#include "../Variant/VariantTo.hpp"
|
#include "../Variant/VariantTo.hpp"
|
||||||
|
|
||||||
#include "../Array/ArraySubscript.hpp"
|
#include "../Array/ElementProxy.hpp"
|
||||||
|
#include "../Object/MemberProxy.hpp"
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
@ -81,22 +82,51 @@ class JsonDocument : public Visitable {
|
|||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectSubscript operator[](TKey)
|
ArrayRef createNestedArray() {
|
||||||
// TKey = const std::string&, const String&
|
return add().to<ArrayRef>();
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE typename enable_if<IsString<TKey>::value,
|
|
||||||
ObjectSubscript<const TKey&> >::type
|
|
||||||
operator[](const TKey& key) {
|
|
||||||
return getVariant()[key];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectSubscript operator[](TKey);
|
template <typename TKey>
|
||||||
// TKey = const char*, const char[N], const __FlashStringHelper*
|
ArrayRef createNestedArray(TKey* key) {
|
||||||
|
return getOrCreate(key).template to<ArrayRef>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
ArrayRef createNestedArray(const TKey& key) {
|
||||||
|
return getOrCreate(key).template to<ArrayRef>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectRef createNestedObject() {
|
||||||
|
return add().to<ObjectRef>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
ObjectRef createNestedObject(TKey* key) {
|
||||||
|
return getOrCreate(key).template to<ObjectRef>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
ObjectRef createNestedObject(const TKey& key) {
|
||||||
|
return getOrCreate(key).template to<ObjectRef>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemberProxy operator[](TKey)
|
||||||
|
// TKey = const std::string&, const String&
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
FORCE_INLINE
|
FORCE_INLINE
|
||||||
typename enable_if<IsString<TKey*>::value, ObjectSubscript<TKey*> >::type
|
typename enable_if<IsString<TKey>::value,
|
||||||
|
MemberProxy<JsonDocument&, const TKey&> >::type
|
||||||
|
operator[](const TKey& key) {
|
||||||
|
return MemberProxy<JsonDocument&, const TKey&>(*this, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemberProxy operator[](TKey);
|
||||||
|
// TKey = const char*, const char[N], const __FlashStringHelper*
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE typename enable_if<IsString<TKey*>::value,
|
||||||
|
MemberProxy<JsonDocument&, TKey*> >::type
|
||||||
operator[](TKey* key) {
|
operator[](TKey* key) {
|
||||||
return getVariant()[key];
|
return MemberProxy<JsonDocument&, TKey*>(*this, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// VariantConstRef operator[](TKey) const
|
// VariantConstRef operator[](TKey) const
|
||||||
@ -115,12 +145,56 @@ class JsonDocument : public Visitable {
|
|||||||
return getVariant()[key];
|
return getVariant()[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE ArraySubscript operator[](size_t index) {
|
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
|
||||||
return getVariant()[index];
|
return ElementProxy<JsonDocument&>(*this, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
FORCE_INLINE VariantConstRef operator[](size_t index) const {
|
||||||
return getVariant()[index];
|
return VariantConstRef(_data.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE VariantRef get(size_t index) {
|
||||||
|
return VariantRef(&_pool, _data.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE VariantRef get(TKey* key) {
|
||||||
|
return VariantRef(&_pool, _data.get(wrapString(key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get(
|
||||||
|
const TKey& key) {
|
||||||
|
return VariantRef(&_pool, _data.get(wrapString(key)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE VariantRef getOrCreate(TKey* key) {
|
||||||
|
return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE VariantRef getOrCreate(const TKey& key) {
|
||||||
|
return VariantRef(&_pool, _data.getOrCreate(wrapString(key), &_pool));
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE VariantRef add() {
|
||||||
|
return VariantRef(&_pool, _data.add(&_pool));
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool add(TValue);
|
||||||
|
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
|
||||||
|
// std::string, String, ObjectRef
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE bool add(const T& value) {
|
||||||
|
return add().set(value);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// bool add(TValue);
|
||||||
|
// TValue = char*, const char*, const __FlashStringHelper*
|
||||||
|
template <typename T>
|
||||||
|
FORCE_INLINE bool add(T* value) {
|
||||||
|
return add().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -15,4 +15,7 @@ struct Visitable {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsVisitable : is_base_of<Visitable, T> {};
|
struct IsVisitable : is_base_of<Visitable, T> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct IsVisitable<T&> : IsVisitable<T> {};
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -15,21 +15,21 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TStringRef>
|
template <typename TObject, typename TString>
|
||||||
class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >,
|
class MemberProxy : public VariantOperators<MemberProxy<TObject, TString> >,
|
||||||
public Visitable {
|
public Visitable {
|
||||||
typedef ObjectSubscript<TStringRef> this_type;
|
typedef MemberProxy<TObject, TString> this_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FORCE_INLINE ObjectSubscript(ObjectRef object, TStringRef key)
|
FORCE_INLINE MemberProxy(TObject variant, TString key)
|
||||||
: _object(object), _key(key) {}
|
: _object(variant), _key(key) {}
|
||||||
|
|
||||||
operator VariantConstRef() const {
|
FORCE_INLINE operator VariantConstRef() const {
|
||||||
return get_impl();
|
return getMember();
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE this_type &operator=(const this_type &src) {
|
FORCE_INLINE this_type &operator=(const this_type &src) {
|
||||||
set_impl().set(src);
|
getOrCreateMember().set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >,
|
|||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
|
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
|
||||||
operator=(const TValue &src) {
|
operator=(const TValue &src) {
|
||||||
set_impl().set(src);
|
getOrCreateMember().set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@ -49,27 +49,27 @@ class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >,
|
|||||||
// TValue = char*, const char*, const __FlashStringHelper*
|
// TValue = char*, const char*, const __FlashStringHelper*
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE this_type &operator=(TValue *src) {
|
FORCE_INLINE this_type &operator=(TValue *src) {
|
||||||
set_impl().set(src);
|
getOrCreateMember().set(src);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return get_impl().isNull();
|
return getMember().isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE typename VariantAs<TValue>::type as() const {
|
FORCE_INLINE typename VariantAs<TValue>::type as() const {
|
||||||
return get_impl().template as<TValue>();
|
return getMember().template as<TValue>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool is() const {
|
FORCE_INLINE bool is() const {
|
||||||
return get_impl().template is<TValue>();
|
return getMember().template is<TValue>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE typename VariantTo<TValue>::type to() {
|
FORCE_INLINE typename VariantTo<TValue>::type to() {
|
||||||
return set_impl().template to<TValue>();
|
return getOrCreateMember().template to<TValue>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the specified value.
|
// Sets the specified value.
|
||||||
@ -81,48 +81,73 @@ class ObjectSubscript : public VariantOperators<ObjectSubscript<TStringRef> >,
|
|||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
|
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
|
||||||
const TValue &value) {
|
const TValue &value) {
|
||||||
return set_impl().set(value);
|
return getOrCreateMember().set(value);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool set(TValue);
|
// bool set(TValue);
|
||||||
// TValue = char*, const char, const __FlashStringHelper*
|
// TValue = char*, const char, const __FlashStringHelper*
|
||||||
template <typename TValue>
|
template <typename TValue>
|
||||||
FORCE_INLINE bool set(const TValue *value) {
|
FORCE_INLINE bool set(const TValue *value) {
|
||||||
return set_impl().set(value);
|
return getOrCreateMember().set(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
void accept(Visitor &visitor) const {
|
void accept(Visitor &visitor) const {
|
||||||
return get_impl().accept(visitor);
|
return getMember().accept(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
using ArrayShortcuts<MemberProxy>::add;
|
||||||
|
FORCE_INLINE VariantRef add() const {
|
||||||
|
return getOrCreateMember().add();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
FORCE_INLINE VariantRef get(TNestedKey *key) const {
|
||||||
|
return getMember().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
FORCE_INLINE VariantRef get(const TNestedKey &key) const {
|
||||||
|
return getMember().get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
FORCE_INLINE VariantRef getOrCreate(TNestedKey *key) const {
|
||||||
|
return getOrCreateMember().getOrCreate(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TNestedKey>
|
||||||
|
FORCE_INLINE VariantRef getOrCreate(const TNestedKey &key) const {
|
||||||
|
return getOrCreateMember().getOrCreate(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FORCE_INLINE VariantRef get_impl() const {
|
FORCE_INLINE VariantRef getMember() const {
|
||||||
return _object.get(_key);
|
return _object.get(_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantRef set_impl() const {
|
FORCE_INLINE VariantRef getOrCreateMember() const {
|
||||||
return _object.set(_key);
|
return _object.getOrCreate(_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectRef _object;
|
TObject _object;
|
||||||
TStringRef _key;
|
TString _key;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TImpl>
|
template <typename TObject>
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
inline typename enable_if<IsString<TString>::value,
|
inline typename enable_if<IsString<TString>::value,
|
||||||
ObjectSubscript<const TString &> >::type
|
MemberProxy<const TObject &, const TString &> >::type
|
||||||
VariantSubscripts<TImpl>::operator[](const TString &key) const {
|
ObjectShortcuts<TObject>::operator[](const TString &key) const {
|
||||||
return impl()->template as<ObjectRef>()[key];
|
return MemberProxy<const TObject &, const TString &>(*impl(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TImpl>
|
template <typename TObject>
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
inline typename enable_if<IsString<TString *>::value,
|
inline typename enable_if<IsString<TString *>::value,
|
||||||
ObjectSubscript<TString *> >::type
|
MemberProxy<const TObject &, TString *> >::type
|
||||||
VariantSubscripts<TImpl>::operator[](TString *key) const {
|
ObjectShortcuts<TObject>::operator[](TString *key) const {
|
||||||
return impl()->template as<ObjectRef>()[key];
|
return MemberProxy<const TObject &, TString *>(*impl(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -40,7 +40,8 @@ void objectRemove(CollectionData *obj, TKey key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
inline VariantData *objectSet(CollectionData *obj, TKey key, MemoryPool *pool) {
|
inline VariantData *objectGetOrCreate(CollectionData *obj, TKey key,
|
||||||
|
MemoryPool *pool) {
|
||||||
if (!obj) return 0;
|
if (!obj) return 0;
|
||||||
|
|
||||||
// ignore null key
|
// ignore null key
|
||||||
|
@ -9,13 +9,31 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TObject>
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
inline ArrayRef ObjectRef::createNestedArray(const TString& key) const {
|
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
|
||||||
return set(key).template to<ArrayRef>();
|
const TString& key) const {
|
||||||
|
return impl()->getOrCreate(key).template to<ArrayRef>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TObject>
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
inline ArrayRef ObjectRef::createNestedArray(TString* key) const {
|
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
|
||||||
return set(key).template to<ArrayRef>();
|
TString* key) const {
|
||||||
|
return impl()->getOrCreate(key).template to<ArrayRef>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TObject>
|
||||||
|
template <typename TKey>
|
||||||
|
ObjectRef ObjectShortcuts<TObject>::createNestedObject(const TKey& key) const {
|
||||||
|
return impl()->getOrCreate(key).template to<ObjectRef>();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// ObjectRef createNestedObject(TKey);
|
||||||
|
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
||||||
|
template <typename TObject>
|
||||||
|
template <typename TKey>
|
||||||
|
ObjectRef ObjectShortcuts<TObject>::createNestedObject(TKey* key) const {
|
||||||
|
return impl()->getOrCreate(key).template to<ObjectRef>();
|
||||||
}
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -17,6 +17,10 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
template <typename TData>
|
template <typename TData>
|
||||||
class ObjectRefBase {
|
class ObjectRefBase {
|
||||||
public:
|
public:
|
||||||
|
operator VariantConstRef() const {
|
||||||
|
return VariantConstRef(reinterpret_cast<const VariantData*>(_data));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Visitor>
|
template <typename Visitor>
|
||||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||||
objectAccept(_data, visitor);
|
objectAccept(_data, visitor);
|
||||||
@ -127,7 +131,9 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
|
class ObjectRef : public ObjectRefBase<CollectionData>,
|
||||||
|
public ObjectShortcuts<ObjectRef>,
|
||||||
|
public Visitable {
|
||||||
typedef ObjectRefBase<CollectionData> base_type;
|
typedef ObjectRefBase<CollectionData> base_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -164,68 +170,30 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
|
|||||||
return _data->copyFrom(*src._data, _pool);
|
return _data->copyFrom(*src._data, _pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates and adds a ArrayRef.
|
|
||||||
//
|
|
||||||
// ArrayRef createNestedArray(TKey);
|
|
||||||
// TKey = const std::string&, const String&
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE ArrayRef createNestedArray(const TKey& key) const;
|
|
||||||
// ArrayRef createNestedArray(TKey);
|
|
||||||
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE ArrayRef createNestedArray(TKey* key) const;
|
|
||||||
|
|
||||||
// Creates and adds a ObjectRef.
|
|
||||||
//
|
|
||||||
// ObjectRef createNestedObject(TKey);
|
|
||||||
// TKey = const std::string&, const String&
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE ObjectRef createNestedObject(const TKey& key) const {
|
|
||||||
return set(key).template to<ObjectRef>();
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// ObjectRef createNestedObject(TKey);
|
|
||||||
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE ObjectRef createNestedObject(TKey* key) const {
|
|
||||||
return set(key).template to<ObjectRef>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the value associated with the specified key.
|
// Gets the value associated with the specified key.
|
||||||
//
|
//
|
||||||
// TValue get<TValue>(TKey) const;
|
// VariantRef get<TValue>(TKey) const;
|
||||||
// TKey = const std::string&, const String&
|
// TKey = const std::string&, const String&
|
||||||
// TValue = bool, char, long, int, short, float, double,
|
|
||||||
// std::string, String, ArrayRef, ObjectRef
|
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
FORCE_INLINE VariantRef get(const TKey& key) const {
|
FORCE_INLINE VariantRef get(const TKey& key) const {
|
||||||
return get_impl(wrapString(key));
|
return get_impl(wrapString(key));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// TValue get<TValue>(TKey) const;
|
// VariantRef get<TValue>(TKey) const;
|
||||||
// TKey = char*, const char*, const __FlashStringHelper*
|
// TKey = char*, const char*, const __FlashStringHelper*
|
||||||
// TValue = bool, char, long, int, short, float, double,
|
|
||||||
// std::string, String, ArrayRef, ObjectRef
|
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
FORCE_INLINE VariantRef get(TKey* key) const {
|
FORCE_INLINE VariantRef get(TKey* key) const {
|
||||||
return get_impl(wrapString(key));
|
return get_impl(wrapString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets the value associated with the specified key.
|
|
||||||
//
|
|
||||||
// ObjectSubscript operator[](TKey)
|
|
||||||
// TKey = const std::string&, const String&
|
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
FORCE_INLINE ObjectSubscript<const TKey&> operator[](const TKey& key) const {
|
FORCE_INLINE VariantRef getOrCreate(TKey* key) const {
|
||||||
return ObjectSubscript<const TKey&>(*this, key);
|
return getOrCreate_impl(wrapString(key));
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// ObjectSubscript operator[](TKey)
|
|
||||||
// TKey = char*, const char*, char[], const char[N], const
|
|
||||||
// __FlashStringHelper*
|
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
FORCE_INLINE ObjectSubscript<TKey*> operator[](TKey* key) const {
|
FORCE_INLINE VariantRef getOrCreate(const TKey& key) const {
|
||||||
return ObjectSubscript<TKey*>(*this, key);
|
return getOrCreate_impl(wrapString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE bool operator==(ObjectRef rhs) const {
|
FORCE_INLINE bool operator==(ObjectRef rhs) const {
|
||||||
@ -253,16 +221,6 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
|
|||||||
objectRemove(_data, wrapString(key));
|
objectRemove(_data, wrapString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE VariantRef set(TKey* key) const {
|
|
||||||
return set_impl(wrapString(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE VariantRef set(const TKey& key) const {
|
|
||||||
return set_impl(wrapString(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
FORCE_INLINE VariantRef get_impl(TKey key) const {
|
FORCE_INLINE VariantRef get_impl(TKey key) const {
|
||||||
@ -270,8 +228,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>, public Visitable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
FORCE_INLINE VariantRef set_impl(TKey key) const {
|
FORCE_INLINE VariantRef getOrCreate_impl(TKey key) const {
|
||||||
return VariantRef(_pool, objectSet(_data, key, _pool));
|
return VariantRef(_pool, objectGetOrCreate(_data, key, _pool));
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryPool* _pool;
|
MemoryPool* _pool;
|
||||||
|
61
src/ArduinoJson/Object/ObjectShortcuts.hpp
Normal file
61
src/ArduinoJson/Object/ObjectShortcuts.hpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Polyfills/attributes.hpp"
|
||||||
|
#include "../Polyfills/type_traits.hpp"
|
||||||
|
#include "../Strings/StringWrappers.hpp"
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
template <typename TParent, typename TKey>
|
||||||
|
class MemberProxy;
|
||||||
|
|
||||||
|
template <typename TObject>
|
||||||
|
class ObjectShortcuts {
|
||||||
|
public:
|
||||||
|
// MemberProxy operator[](TKey) const;
|
||||||
|
// TKey = const std::string&, const String&
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE
|
||||||
|
typename enable_if<IsString<TKey>::value,
|
||||||
|
MemberProxy<const TObject &, const TKey &> >::type
|
||||||
|
operator[](const TKey &key) const;
|
||||||
|
//
|
||||||
|
// MemberProxy operator[](TKey) const;
|
||||||
|
// TKey = const char*, const char[N], const __FlashStringHelper*
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE typename enable_if<IsString<TKey *>::value,
|
||||||
|
MemberProxy<const TObject &, TKey *> >::type
|
||||||
|
operator[](TKey *key) const;
|
||||||
|
|
||||||
|
// Creates and adds a ArrayRef.
|
||||||
|
//
|
||||||
|
// ArrayRef createNestedArray(TKey);
|
||||||
|
// TKey = const std::string&, const String&
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE ArrayRef createNestedArray(const TKey &key) const;
|
||||||
|
// ArrayRef createNestedArray(TKey);
|
||||||
|
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE ArrayRef createNestedArray(TKey *key) const;
|
||||||
|
|
||||||
|
// Creates and adds a ObjectRef.
|
||||||
|
//
|
||||||
|
// ObjectRef createNestedObject(TKey);
|
||||||
|
// TKey = const std::string&, const String&
|
||||||
|
template <typename TKey>
|
||||||
|
ObjectRef createNestedObject(const TKey &key) const;
|
||||||
|
//
|
||||||
|
// ObjectRef createNestedObject(TKey);
|
||||||
|
// TKey = char*, const char*, char[], const char[], const __FlashStringHelper*
|
||||||
|
template <typename TKey>
|
||||||
|
ObjectRef createNestedObject(TKey *key) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const TObject *impl() const {
|
||||||
|
return static_cast<const TObject *>(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -7,7 +7,7 @@
|
|||||||
#include "VariantCasts.hpp"
|
#include "VariantCasts.hpp"
|
||||||
#include "VariantComparisons.hpp"
|
#include "VariantComparisons.hpp"
|
||||||
#include "VariantOr.hpp"
|
#include "VariantOr.hpp"
|
||||||
#include "VariantSubscripts.hpp"
|
#include "VariantShortcuts.hpp"
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
@ -15,5 +15,5 @@ template <typename TImpl>
|
|||||||
class VariantOperators : public VariantCasts<TImpl>,
|
class VariantOperators : public VariantCasts<TImpl>,
|
||||||
public VariantComparisons<TImpl>,
|
public VariantComparisons<TImpl>,
|
||||||
public VariantOr<TImpl>,
|
public VariantOr<TImpl>,
|
||||||
public VariantSubscripts<TImpl> {};
|
public VariantShortcuts<TImpl> {};
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
23
src/ArduinoJson/Operators/VariantShortcuts.hpp
Normal file
23
src/ArduinoJson/Operators/VariantShortcuts.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Array/ArrayShortcuts.hpp"
|
||||||
|
#include "../Object/ObjectShortcuts.hpp"
|
||||||
|
|
||||||
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
template <typename TVariant>
|
||||||
|
class VariantShortcuts : public ObjectShortcuts<TVariant>,
|
||||||
|
public ArrayShortcuts<TVariant> {
|
||||||
|
public:
|
||||||
|
using ArrayShortcuts<TVariant>::createNestedArray;
|
||||||
|
using ArrayShortcuts<TVariant>::createNestedObject;
|
||||||
|
using ArrayShortcuts<TVariant>::operator[];
|
||||||
|
using ObjectShortcuts<TVariant>::createNestedArray;
|
||||||
|
using ObjectShortcuts<TVariant>::createNestedObject;
|
||||||
|
using ObjectShortcuts<TVariant>::operator[];
|
||||||
|
};
|
||||||
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,51 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2018
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Polyfills/attributes.hpp"
|
|
||||||
#include "../Polyfills/type_traits.hpp"
|
|
||||||
#include "../Strings/StringWrappers.hpp"
|
|
||||||
#include "../Variant/VariantAs.hpp"
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
class ArrayRef;
|
|
||||||
class ObjectRef;
|
|
||||||
|
|
||||||
// Forward declarations.
|
|
||||||
class ArraySubscript;
|
|
||||||
template <typename TKey>
|
|
||||||
class ObjectSubscript;
|
|
||||||
|
|
||||||
template <typename TImpl>
|
|
||||||
class VariantSubscripts {
|
|
||||||
public:
|
|
||||||
// Mimics an array.
|
|
||||||
// Returns the element at specified index if the variant is an array.
|
|
||||||
FORCE_INLINE ArraySubscript operator[](size_t index) const;
|
|
||||||
|
|
||||||
// Mimics an object.
|
|
||||||
// Returns the value associated with the specified key if the variant is
|
|
||||||
// an object.
|
|
||||||
//
|
|
||||||
// ObjectSubscript operator[](TKey) const;
|
|
||||||
// TKey = const std::string&, const String&
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE typename enable_if<IsString<TKey>::value,
|
|
||||||
ObjectSubscript<const TKey &> >::type
|
|
||||||
operator[](const TKey &key) const;
|
|
||||||
//
|
|
||||||
// ObjectSubscript operator[](TKey) const;
|
|
||||||
// TKey = const char*, const char[N], const __FlashStringHelper*
|
|
||||||
template <typename TKey>
|
|
||||||
FORCE_INLINE typename enable_if<IsString<TKey *>::value,
|
|
||||||
ObjectSubscript<TKey *> >::type
|
|
||||||
operator[](TKey *key) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const TImpl *impl() const {
|
|
||||||
return static_cast<const TImpl *>(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
@ -12,19 +12,24 @@
|
|||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
|
//
|
||||||
enum {
|
enum {
|
||||||
VALUE_IS_NULL = 0,
|
|
||||||
VALUE_IS_LINKED_RAW,
|
|
||||||
VALUE_IS_OWNED_RAW,
|
|
||||||
VALUE_IS_LINKED_STRING,
|
|
||||||
VALUE_IS_OWNED_STRING,
|
|
||||||
VALUE_IS_BOOLEAN,
|
|
||||||
VALUE_IS_POSITIVE_INTEGER,
|
|
||||||
VALUE_IS_NEGATIVE_INTEGER,
|
|
||||||
VALUE_IS_ARRAY,
|
|
||||||
VALUE_IS_OBJECT,
|
|
||||||
VALUE_IS_FLOAT,
|
|
||||||
VALUE_MASK = 0x7F,
|
VALUE_MASK = 0x7F,
|
||||||
|
|
||||||
|
VALUE_IS_NULL = 0,
|
||||||
|
VALUE_IS_LINKED_RAW = 0x01,
|
||||||
|
VALUE_IS_OWNED_RAW = 0x02,
|
||||||
|
VALUE_IS_LINKED_STRING = 0x03,
|
||||||
|
VALUE_IS_OWNED_STRING = 0x04,
|
||||||
|
VALUE_IS_BOOLEAN = 0x05,
|
||||||
|
VALUE_IS_POSITIVE_INTEGER = 0x06,
|
||||||
|
VALUE_IS_NEGATIVE_INTEGER = 0x07,
|
||||||
|
VALUE_IS_FLOAT = 0x08,
|
||||||
|
|
||||||
|
COLLECTION_MASK = 0x60,
|
||||||
|
VALUE_IS_OBJECT = 0x20,
|
||||||
|
VALUE_IS_ARRAY = 0x40,
|
||||||
|
|
||||||
KEY_IS_OWNED = 0x80
|
KEY_IS_OWNED = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CollectionData *asArray() {
|
CollectionData *asArray() {
|
||||||
return type() == VALUE_IS_ARRAY ? &_content.asCollection : 0;
|
return isArray() ? &_content.asCollection : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollectionData *asArray() const {
|
const CollectionData *asArray() const {
|
||||||
@ -75,7 +75,7 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CollectionData *asObject() {
|
CollectionData *asObject() {
|
||||||
return type() == VALUE_IS_OBJECT ? &_content.asCollection : 0;
|
return isObject() ? &_content.asCollection : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollectionData *asObject() const {
|
const CollectionData *asObject() const {
|
||||||
@ -135,13 +135,17 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isArray() const {
|
bool isArray() const {
|
||||||
return type() == VALUE_IS_ARRAY;
|
return (_flags & VALUE_IS_ARRAY) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBoolean() const {
|
bool isBoolean() const {
|
||||||
return type() == VALUE_IS_BOOLEAN;
|
return type() == VALUE_IS_BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isCollection() const {
|
||||||
|
return (_flags & COLLECTION_MASK) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool isInteger() const {
|
bool isInteger() const {
|
||||||
return type() == VALUE_IS_POSITIVE_INTEGER ||
|
return type() == VALUE_IS_POSITIVE_INTEGER ||
|
||||||
type() == VALUE_IS_NEGATIVE_INTEGER;
|
type() == VALUE_IS_NEGATIVE_INTEGER;
|
||||||
@ -153,12 +157,11 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isString() const {
|
bool isString() const {
|
||||||
return (type() == VALUE_IS_LINKED_STRING ||
|
return type() == VALUE_IS_LINKED_STRING || type() == VALUE_IS_OWNED_STRING;
|
||||||
type() == VALUE_IS_OWNED_STRING);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isObject() const {
|
bool isObject() const {
|
||||||
return type() == VALUE_IS_OBJECT;
|
return (_flags & VALUE_IS_OBJECT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
@ -275,20 +278,35 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t nesting() const {
|
size_t nesting() const {
|
||||||
switch (type()) {
|
return isCollection() ? _content.asCollection.nesting() : 0;
|
||||||
case VALUE_IS_OBJECT:
|
|
||||||
case VALUE_IS_ARRAY:
|
|
||||||
return _content.asCollection.nesting();
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
if (type() == VALUE_IS_OBJECT || type() == VALUE_IS_ARRAY)
|
return isCollection() ? _content.asCollection.size() : 0;
|
||||||
return _content.asCollection.size();
|
}
|
||||||
else
|
|
||||||
return 0;
|
VariantData *get(size_t index) const {
|
||||||
|
return isArray() ? _content.asCollection.get(index) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
VariantData *get(TKey key) const {
|
||||||
|
return isObject() ? _content.asCollection.get(key) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
VariantData *getOrCreate(TKey key, MemoryPool *pool) {
|
||||||
|
if (isNull()) toObject();
|
||||||
|
if (!isObject()) return 0;
|
||||||
|
VariantData *var = _content.asCollection.get(key);
|
||||||
|
if (var) return var;
|
||||||
|
return _content.asCollection.add(key, pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
VariantData *add(MemoryPool *pool) {
|
||||||
|
if (isNull()) toArray();
|
||||||
|
if (!isArray()) return 0;
|
||||||
|
return _content.asCollection.add(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -146,4 +146,20 @@ inline CollectionData *variantToObject(VariantData *var) {
|
|||||||
return &var->toObject();
|
return &var->toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline NO_INLINE VariantData *variantAdd(VariantData *var, MemoryPool *pool) {
|
||||||
|
return var != 0 ? var->add(pool) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, TKey *key,
|
||||||
|
MemoryPool *pool) {
|
||||||
|
return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
NO_INLINE VariantData *variantGetOrCreate(VariantData *var, const TKey &key,
|
||||||
|
MemoryPool *pool) {
|
||||||
|
return var != 0 ? var->getOrCreate(wrapString(key), pool) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -60,37 +60,11 @@ inline const char* VariantData::asString() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool VariantRef::set(ArrayRef array) const {
|
template <typename TVariant>
|
||||||
return to<ArrayRef>().copyFrom(array);
|
typename enable_if<IsVisitable<TVariant>::value, bool>::type VariantRef::set(
|
||||||
}
|
const TVariant &value) const {
|
||||||
|
VariantConstRef v = value;
|
||||||
inline bool VariantRef::set(ArrayConstRef array) const {
|
return variantCopyFrom(_data, v._data, _pool);
|
||||||
return to<ArrayRef>().copyFrom(array);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VariantRef::set(const ArraySubscript& value) const {
|
|
||||||
return set(value.as<VariantRef>());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VariantRef::set(ObjectRef object) const {
|
|
||||||
return to<ObjectRef>().copyFrom(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VariantRef::set(ObjectConstRef object) const {
|
|
||||||
return to<ObjectRef>().copyFrom(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TString>
|
|
||||||
inline bool VariantRef::set(const ObjectSubscript<TString>& value) const {
|
|
||||||
return set(value.template as<VariantRef>());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VariantRef::set(VariantConstRef value) const {
|
|
||||||
return variantCopyFrom(_data, value._data, _pool);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool VariantRef::set(VariantRef value) const {
|
|
||||||
return variantCopyFrom(_data, value._data, _pool);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -128,4 +102,32 @@ inline VariantConstRef VariantConstRef::operator[](size_t index) const {
|
|||||||
return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
|
return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline VariantRef VariantRef::add() const {
|
||||||
|
return VariantRef(_pool, variantAdd(_data, _pool));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline VariantRef VariantRef::get(size_t index) const {
|
||||||
|
return VariantRef(_pool, _data != 0 ? _data->get(index) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
inline VariantRef VariantRef::get(TKey *key) const {
|
||||||
|
return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
inline typename enable_if<IsString<TKey>::value, VariantRef>::type
|
||||||
|
VariantRef::get(const TKey &key) const {
|
||||||
|
return VariantRef(_pool, _data != 0 ? _data->get(wrapString(key)) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
inline VariantRef VariantRef::getOrCreate(TKey *key) const {
|
||||||
|
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
inline VariantRef VariantRef::getOrCreate(const TKey &key) const {
|
||||||
|
return VariantRef(_pool, variantGetOrCreate(_data, key, _pool));
|
||||||
|
}
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
||||||
|
@ -23,6 +23,9 @@ namespace ARDUINOJSON_NAMESPACE {
|
|||||||
class ArrayRef;
|
class ArrayRef;
|
||||||
class ObjectRef;
|
class ObjectRef;
|
||||||
|
|
||||||
|
template <typename, typename>
|
||||||
|
class MemberProxy;
|
||||||
|
|
||||||
// Contains the methods shared by VariantRef and VariantConstRef
|
// Contains the methods shared by VariantRef and VariantConstRef
|
||||||
template <typename TData>
|
template <typename TData>
|
||||||
class VariantRefBase {
|
class VariantRefBase {
|
||||||
@ -207,16 +210,15 @@ class VariantRef : public VariantRefBase<VariantData>,
|
|||||||
return variantSetLinkedString(_data, value);
|
return variantSetLinkedString(_data, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set(VariantConstRef value) const;
|
// set(VariantRef)
|
||||||
bool set(VariantRef value) const;
|
// set(VariantConstRef)
|
||||||
|
// set(ArrayRef)
|
||||||
FORCE_INLINE bool set(ArrayRef array) const;
|
// set(ArrayConstRef)
|
||||||
FORCE_INLINE bool set(ArrayConstRef array) const;
|
// set(ObjectRef)
|
||||||
FORCE_INLINE bool set(const ArraySubscript &) const;
|
// set(ObjecConstRef)
|
||||||
FORCE_INLINE bool set(ObjectRef object) const;
|
template <typename TVariant>
|
||||||
FORCE_INLINE bool set(ObjectConstRef object) const;
|
typename enable_if<IsVisitable<TVariant>::value, bool>::type set(
|
||||||
template <typename TString>
|
const TVariant &value) const;
|
||||||
FORCE_INLINE bool set(const ObjectSubscript<TString> &) const;
|
|
||||||
|
|
||||||
// Get the variant as the specified type.
|
// Get the variant as the specified type.
|
||||||
//
|
//
|
||||||
@ -278,6 +280,26 @@ class VariantRef : public VariantRefBase<VariantData>,
|
|||||||
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
|
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
|
||||||
const;
|
const;
|
||||||
|
|
||||||
|
VariantRef add() const;
|
||||||
|
using ArrayShortcuts::add;
|
||||||
|
|
||||||
|
FORCE_INLINE VariantRef get(size_t) const;
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE VariantRef get(TKey *) const;
|
||||||
|
|
||||||
|
// get(const char*)
|
||||||
|
// get(const __FlashStringHelper*)
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE typename enable_if<IsString<TKey>::value, VariantRef>::type get(
|
||||||
|
const TKey &) const;
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE VariantRef getOrCreate(TKey *) const;
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
FORCE_INLINE VariantRef getOrCreate(const TKey &) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryPool *_pool;
|
MemoryPool *_pool;
|
||||||
};
|
};
|
||||||
|
@ -71,6 +71,7 @@ if(MSVC)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(ElementProxy)
|
||||||
add_subdirectory(IntegrationTests)
|
add_subdirectory(IntegrationTests)
|
||||||
add_subdirectory(JsonArray)
|
add_subdirectory(JsonArray)
|
||||||
add_subdirectory(JsonDeserializer)
|
add_subdirectory(JsonDeserializer)
|
||||||
@ -78,10 +79,11 @@ add_subdirectory(JsonDocument)
|
|||||||
add_subdirectory(JsonObject)
|
add_subdirectory(JsonObject)
|
||||||
add_subdirectory(JsonSerializer)
|
add_subdirectory(JsonSerializer)
|
||||||
add_subdirectory(JsonVariant)
|
add_subdirectory(JsonVariant)
|
||||||
add_subdirectory(TextFormatter)
|
add_subdirectory(MemberProxy)
|
||||||
add_subdirectory(MemoryPool)
|
add_subdirectory(MemoryPool)
|
||||||
add_subdirectory(Misc)
|
add_subdirectory(Misc)
|
||||||
add_subdirectory(MixedConfiguration)
|
add_subdirectory(MixedConfiguration)
|
||||||
add_subdirectory(MsgPackDeserializer)
|
add_subdirectory(MsgPackDeserializer)
|
||||||
add_subdirectory(MsgPackSerializer)
|
add_subdirectory(MsgPackSerializer)
|
||||||
add_subdirectory(Numbers)
|
add_subdirectory(Numbers)
|
||||||
|
add_subdirectory(TextFormatter)
|
||||||
|
11
test/ElementProxy/CMakeLists.txt
Normal file
11
test/ElementProxy/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# ArduinoJson - arduinojson.org
|
||||||
|
# Copyright Benoit Blanchon 2014-2018
|
||||||
|
# MIT License
|
||||||
|
|
||||||
|
add_executable(ElementProxyTests
|
||||||
|
add.cpp
|
||||||
|
set.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(ElementProxyTests catch)
|
||||||
|
add_test(ElementProxy ElementProxyTests)
|
26
test/ElementProxy/add.cpp
Normal file
26
test/ElementProxy/add.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
|
TEST_CASE("ElementProxy::add()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
doc.add();
|
||||||
|
ElementProxy<JsonDocument&> ep = doc[0];
|
||||||
|
|
||||||
|
SECTION("add(int)") {
|
||||||
|
ep.add(42);
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "[[42]]");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("add(const char*)") {
|
||||||
|
ep.add("world");
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "[[\"world\"]]");
|
||||||
|
}
|
||||||
|
}
|
26
test/ElementProxy/set.cpp
Normal file
26
test/ElementProxy/set.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
|
TEST_CASE("ElementProxy::set()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
doc.add();
|
||||||
|
ElementProxy<JsonDocument&> ep = doc[0];
|
||||||
|
|
||||||
|
SECTION("set(int)") {
|
||||||
|
ep.set(42);
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "[42]");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(const char*)") {
|
||||||
|
ep.set("world");
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "[\"world\"]");
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,11 @@
|
|||||||
# MIT License
|
# MIT License
|
||||||
|
|
||||||
add_executable(JsonDocumentTests
|
add_executable(JsonDocumentTests
|
||||||
|
add.cpp
|
||||||
|
createNested.cpp
|
||||||
DynamicJsonDocument.cpp
|
DynamicJsonDocument.cpp
|
||||||
nesting.cpp
|
|
||||||
isNull.cpp
|
isNull.cpp
|
||||||
|
nesting.cpp
|
||||||
StaticJsonDocument.cpp
|
StaticJsonDocument.cpp
|
||||||
subscript.cpp
|
subscript.cpp
|
||||||
)
|
)
|
||||||
|
22
test/JsonDocument/add.cpp
Normal file
22
test/JsonDocument/add.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::add()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
|
SECTION("integer") {
|
||||||
|
doc.add(42);
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "[42]");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char*") {
|
||||||
|
doc.add("hello");
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "[\"hello\"]");
|
||||||
|
}
|
||||||
|
}
|
66
test/JsonDocument/createNested.cpp
Normal file
66
test/JsonDocument/createNested.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::createNestedArray()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
|
SECTION("promotes to array") {
|
||||||
|
doc.createNestedArray();
|
||||||
|
|
||||||
|
REQUIRE(doc.is<JsonArray>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::createNestedArray(key)") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
|
SECTION("key is const char*") {
|
||||||
|
SECTION("promotes to object") {
|
||||||
|
doc.createNestedArray("hello");
|
||||||
|
|
||||||
|
REQUIRE(doc.is<JsonObject>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("key is std::string") {
|
||||||
|
SECTION("promotes to object") {
|
||||||
|
doc.createNestedArray(std::string("hello"));
|
||||||
|
|
||||||
|
REQUIRE(doc.is<JsonObject>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::createNestedObject()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
|
SECTION("promotes to array") {
|
||||||
|
doc.createNestedObject();
|
||||||
|
|
||||||
|
REQUIRE(doc.is<JsonArray>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonDocument::createNestedObject(key)") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
|
SECTION("key is const char*") {
|
||||||
|
SECTION("promotes to object") {
|
||||||
|
doc.createNestedObject("hello");
|
||||||
|
|
||||||
|
REQUIRE(doc.is<JsonObject>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("key is std::string") {
|
||||||
|
SECTION("promotes to object") {
|
||||||
|
doc.createNestedObject(std::string("hello"));
|
||||||
|
|
||||||
|
REQUIRE(doc.is<JsonObject>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,11 @@ TEST_CASE("JsonDocument::operator[]") {
|
|||||||
REQUIRE(doc[std::string("hello")] == "world");
|
REQUIRE(doc[std::string("hello")] == "world");
|
||||||
REQUIRE(cdoc[std::string("hello")] == "world");
|
REQUIRE(cdoc[std::string("hello")] == "world");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("supports operator|") {
|
||||||
|
REQUIRE((doc["hello"] | "nope") == std::string("world"));
|
||||||
|
REQUIRE((doc["world"] | "nope") == std::string("nope"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array") {
|
SECTION("array") {
|
||||||
@ -30,3 +35,11 @@ TEST_CASE("JsonDocument::operator[]") {
|
|||||||
REQUIRE(cdoc[1] == "world");
|
REQUIRE(cdoc[1] == "world");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonDocument automatically promotes to object") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
|
||||||
|
doc["one"]["two"]["three"] = 4;
|
||||||
|
|
||||||
|
REQUIRE(doc["one"]["two"]["three"] == 4);
|
||||||
|
}
|
||||||
|
@ -12,7 +12,7 @@ void check(T value, const std::string &expected) {
|
|||||||
REQUIRE(expected.size() == returnValue);
|
REQUIRE(expected.size() == returnValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("serializeJson(JsonObjectSubscript)") {
|
TEST_CASE("serializeJson(MemberProxy)") {
|
||||||
DynamicJsonDocument doc(4096);
|
DynamicJsonDocument doc(4096);
|
||||||
deserializeJson(doc, "{\"hello\":42}");
|
deserializeJson(doc, "{\"hello\":42}");
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
JsonObject obj = doc.as<JsonObject>();
|
||||||
@ -23,7 +23,7 @@ TEST_CASE("serializeJson(JsonObjectSubscript)") {
|
|||||||
REQUIRE(result == "42");
|
REQUIRE(result == "42");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("serializeJson(JsonArraySubscript)") {
|
TEST_CASE("serializeJson(ElementProxy)") {
|
||||||
DynamicJsonDocument doc(4096);
|
DynamicJsonDocument doc(4096);
|
||||||
deserializeJson(doc, "[42]");
|
deserializeJson(doc, "[42]");
|
||||||
JsonArray arr = doc.as<JsonArray>();
|
JsonArray arr = doc.as<JsonArray>();
|
||||||
|
@ -37,7 +37,7 @@ TEST_CASE("operator<<(std::ostream)") {
|
|||||||
REQUIRE("{\"key\":\"value\"}" == os.str());
|
REQUIRE("{\"key\":\"value\"}" == os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonObjectSubscript") {
|
SECTION("MemberProxy") {
|
||||||
JsonObject object = doc.to<JsonObject>();
|
JsonObject object = doc.to<JsonObject>();
|
||||||
object["key"] = "value";
|
object["key"] = "value";
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ TEST_CASE("operator<<(std::ostream)") {
|
|||||||
REQUIRE("[\"value\"]" == os.str());
|
REQUIRE("[\"value\"]" == os.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonArraySubscript") {
|
SECTION("ElementProxy") {
|
||||||
JsonArray array = doc.to<JsonArray>();
|
JsonArray array = doc.to<JsonArray>();
|
||||||
array.add("value");
|
array.add("value");
|
||||||
|
|
||||||
|
@ -3,18 +3,21 @@
|
|||||||
# MIT License
|
# MIT License
|
||||||
|
|
||||||
add_executable(JsonVariantTests
|
add_executable(JsonVariantTests
|
||||||
|
add.cpp
|
||||||
as.cpp
|
as.cpp
|
||||||
compare.cpp
|
compare.cpp
|
||||||
copy.cpp
|
copy.cpp
|
||||||
|
createNested.cpp
|
||||||
get.cpp
|
get.cpp
|
||||||
is.cpp
|
is.cpp
|
||||||
isnull.cpp
|
isnull.cpp
|
||||||
memoryUsage.cpp
|
memoryUsage.cpp
|
||||||
nesting.cpp
|
|
||||||
misc.cpp
|
misc.cpp
|
||||||
|
nesting.cpp
|
||||||
or.cpp
|
or.cpp
|
||||||
set.cpp
|
set.cpp
|
||||||
subscript.cpp
|
subscript.cpp
|
||||||
|
types.cpp
|
||||||
undefined.cpp
|
undefined.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
39
test/JsonVariant/add.cpp
Normal file
39
test/JsonVariant/add.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
static const char* null = 0;
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::add()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
SECTION("No argument") {
|
||||||
|
JsonVariant nested = var.add();
|
||||||
|
|
||||||
|
REQUIRE(var.is<JsonArray>() == true);
|
||||||
|
REQUIRE(nested.isNull() == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("integer") {
|
||||||
|
var.add(42);
|
||||||
|
|
||||||
|
REQUIRE(var.as<std::string>() == "[42]");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("const char*") {
|
||||||
|
var.add("hello");
|
||||||
|
|
||||||
|
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("std::string") {
|
||||||
|
var.add(std::string("hello"));
|
||||||
|
|
||||||
|
REQUIRE(var.as<std::string>() == "[\"hello\"]");
|
||||||
|
}
|
||||||
|
}
|
88
test/JsonVariant/createNested.cpp
Normal file
88
test/JsonVariant/createNested.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
static const char* null = 0;
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::createNestedObject()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
SECTION("promotes to array") {
|
||||||
|
JsonObject obj = variant.createNestedObject();
|
||||||
|
obj["value"] = "42";
|
||||||
|
|
||||||
|
REQUIRE(variant.is<JsonArray>() == true);
|
||||||
|
REQUIRE(variant[0]["value"] == 42);
|
||||||
|
REQUIRE(obj.isNull() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("works on MemberProxy") {
|
||||||
|
JsonObject obj = variant["items"].createNestedObject();
|
||||||
|
obj["value"] = "42";
|
||||||
|
|
||||||
|
REQUIRE(variant["items"][0]["value"] == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::createNestedArray()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
SECTION("promotes to array") {
|
||||||
|
JsonArray arr = variant.createNestedArray();
|
||||||
|
|
||||||
|
REQUIRE(variant.is<JsonArray>() == true);
|
||||||
|
REQUIRE(arr.isNull() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("works on MemberProxy") {
|
||||||
|
JsonArray arr = variant["items"].createNestedArray();
|
||||||
|
arr.add("42");
|
||||||
|
|
||||||
|
REQUIRE(variant["items"][0][0] == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::createNestedObject(key)") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
SECTION("promotes to object") {
|
||||||
|
JsonObject obj = variant.createNestedObject("weather");
|
||||||
|
obj["temp"] = "42";
|
||||||
|
|
||||||
|
REQUIRE(variant.is<JsonObject>() == true);
|
||||||
|
REQUIRE(variant["weather"]["temp"] == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("works on MemberProxy") {
|
||||||
|
JsonObject obj = variant["status"].createNestedObject("weather");
|
||||||
|
obj["temp"] = "42";
|
||||||
|
|
||||||
|
REQUIRE(variant["status"]["weather"]["temp"] == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant::createNestedArray(key)") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
SECTION("promotes to object") {
|
||||||
|
JsonArray arr = variant.createNestedArray("items");
|
||||||
|
|
||||||
|
REQUIRE(variant.is<JsonObject>() == true);
|
||||||
|
REQUIRE(arr.isNull() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("works on MemberProxy") {
|
||||||
|
JsonArray arr = variant["weather"].createNestedArray("temp");
|
||||||
|
arr.add("42");
|
||||||
|
|
||||||
|
REQUIRE(variant["weather"]["temp"][0] == 42);
|
||||||
|
}
|
||||||
|
}
|
@ -3,138 +3,27 @@
|
|||||||
// MIT License
|
// MIT License
|
||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
template <typename T>
|
TEST_CASE("JsonVariant::get()") {
|
||||||
void checkValue(T expected) {
|
|
||||||
DynamicJsonDocument doc(4096);
|
DynamicJsonDocument doc(4096);
|
||||||
JsonVariant variant = doc.to<JsonVariant>();
|
JsonVariant var = doc.to<JsonVariant>();
|
||||||
|
|
||||||
variant.set(expected);
|
SECTION("get(const char*)") {
|
||||||
REQUIRE(expected == variant.as<T>());
|
var["value"] = 42;
|
||||||
|
|
||||||
|
REQUIRE(var.get("value") == 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
SECTION("get(std::string)") {
|
||||||
void checkReference(T &expected) {
|
var["value"] = 42;
|
||||||
JsonVariant variant = expected;
|
|
||||||
REQUIRE(expected == variant.as<T &>());
|
REQUIRE(var.get(std::string("value")) == 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
SECTION("get(int)") {
|
||||||
void checkNumericType() {
|
var.add().set(42);
|
||||||
DynamicJsonDocument docMin(4096), docMax(4096);
|
|
||||||
JsonVariant variantMin = docMin.to<JsonVariant>();
|
|
||||||
JsonVariant variantMax = docMax.to<JsonVariant>();
|
|
||||||
|
|
||||||
T min = std::numeric_limits<T>::min();
|
REQUIRE(var.get(0) == 42);
|
||||||
T max = std::numeric_limits<T>::max();
|
|
||||||
|
|
||||||
variantMin.set(min);
|
|
||||||
variantMax.set(max);
|
|
||||||
|
|
||||||
REQUIRE(min == variantMin.as<T>());
|
|
||||||
REQUIRE(max == variantMax.as<T>());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("JsonVariant set()/get()") {
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
|
||||||
SECTION("SizeOfJsonInteger") {
|
|
||||||
REQUIRE(8 == sizeof(JsonInteger));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SECTION("Null") {
|
|
||||||
checkValue<const char *>(NULL);
|
|
||||||
}
|
|
||||||
SECTION("const char*") {
|
|
||||||
checkValue<const char *>("hello");
|
|
||||||
}
|
|
||||||
SECTION("std::string") {
|
|
||||||
checkValue<std::string>("hello");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("False") {
|
|
||||||
checkValue<bool>(false);
|
|
||||||
}
|
|
||||||
SECTION("True") {
|
|
||||||
checkValue<bool>(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Double") {
|
|
||||||
checkNumericType<double>();
|
|
||||||
}
|
|
||||||
SECTION("Float") {
|
|
||||||
checkNumericType<float>();
|
|
||||||
}
|
|
||||||
SECTION("Char") {
|
|
||||||
checkNumericType<char>();
|
|
||||||
}
|
|
||||||
SECTION("SChar") {
|
|
||||||
checkNumericType<signed char>();
|
|
||||||
}
|
|
||||||
SECTION("SInt") {
|
|
||||||
checkNumericType<signed int>();
|
|
||||||
}
|
|
||||||
SECTION("SLong") {
|
|
||||||
checkNumericType<signed long>();
|
|
||||||
}
|
|
||||||
SECTION("SShort") {
|
|
||||||
checkNumericType<signed short>();
|
|
||||||
}
|
|
||||||
SECTION("UChar") {
|
|
||||||
checkNumericType<unsigned char>();
|
|
||||||
}
|
|
||||||
SECTION("UInt") {
|
|
||||||
checkNumericType<unsigned int>();
|
|
||||||
}
|
|
||||||
SECTION("ULong") {
|
|
||||||
checkNumericType<unsigned long>();
|
|
||||||
}
|
|
||||||
SECTION("UShort") {
|
|
||||||
checkNumericType<unsigned short>();
|
|
||||||
}
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
|
||||||
SECTION("LongLong") {
|
|
||||||
checkNumericType<unsigned long long>();
|
|
||||||
}
|
|
||||||
SECTION("ULongLong") {
|
|
||||||
checkNumericType<unsigned long long>();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SECTION("Int8") {
|
|
||||||
checkNumericType<int8_t>();
|
|
||||||
}
|
|
||||||
SECTION("Uint8") {
|
|
||||||
checkNumericType<uint8_t>();
|
|
||||||
}
|
|
||||||
SECTION("Int16") {
|
|
||||||
checkNumericType<int16_t>();
|
|
||||||
}
|
|
||||||
SECTION("Uint16") {
|
|
||||||
checkNumericType<uint16_t>();
|
|
||||||
}
|
|
||||||
SECTION("Int32") {
|
|
||||||
checkNumericType<int32_t>();
|
|
||||||
}
|
|
||||||
SECTION("Uint32") {
|
|
||||||
checkNumericType<uint32_t>();
|
|
||||||
}
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
|
||||||
SECTION("Int64") {
|
|
||||||
checkNumericType<int64_t>();
|
|
||||||
}
|
|
||||||
SECTION("Uint64") {
|
|
||||||
checkNumericType<uint64_t>();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SECTION("CanStoreObject") {
|
|
||||||
DynamicJsonDocument doc(4096);
|
|
||||||
JsonObject object = doc.to<JsonObject>();
|
|
||||||
|
|
||||||
checkValue<JsonObject>(object);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,8 @@ TEST_CASE("JsonVariant::operator[]") {
|
|||||||
array.add("element at index 1");
|
array.add("element at index 1");
|
||||||
|
|
||||||
REQUIRE(2 == var.size());
|
REQUIRE(2 == var.size());
|
||||||
REQUIRE(std::string("element at index 0") == var[0]);
|
var[0].as<std::string>();
|
||||||
|
// REQUIRE(std::string("element at index 0") == );
|
||||||
REQUIRE(std::string("element at index 1") == var[1]);
|
REQUIRE(std::string("element at index 1") == var[1]);
|
||||||
REQUIRE(std::string("element at index 0") ==
|
REQUIRE(std::string("element at index 0") ==
|
||||||
var[static_cast<unsigned char>(0)]); // issue #381
|
var[static_cast<unsigned char>(0)]); // issue #381
|
||||||
@ -171,4 +172,24 @@ TEST_CASE("JsonVariantConst::operator[]") {
|
|||||||
REQUIRE(cvar[0].isNull());
|
REQUIRE(cvar[0].isNull());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Auto promote null JsonVariant to JsonObject") {
|
||||||
|
var["hello"] = "world";
|
||||||
|
|
||||||
|
REQUIRE(var.is<JsonObject>() == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Don't auto promote non-null JsonVariant to JsonObject") {
|
||||||
|
var.set(42);
|
||||||
|
var["hello"] = "world";
|
||||||
|
|
||||||
|
REQUIRE(var.is<JsonObject>() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Don't auto promote null JsonVariant to JsonObject when reading") {
|
||||||
|
const char* value = var["hello"];
|
||||||
|
|
||||||
|
REQUIRE(var.is<JsonObject>() == false);
|
||||||
|
REQUIRE(value == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
140
test/JsonVariant/types.cpp
Normal file
140
test/JsonVariant/types.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void checkValue(T expected) {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
JsonVariant variant = doc.to<JsonVariant>();
|
||||||
|
|
||||||
|
variant.set(expected);
|
||||||
|
REQUIRE(expected == variant.as<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void checkReference(T &expected) {
|
||||||
|
JsonVariant variant = expected;
|
||||||
|
REQUIRE(expected == variant.as<T &>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void checkNumericType() {
|
||||||
|
DynamicJsonDocument docMin(4096), docMax(4096);
|
||||||
|
JsonVariant variantMin = docMin.to<JsonVariant>();
|
||||||
|
JsonVariant variantMax = docMax.to<JsonVariant>();
|
||||||
|
|
||||||
|
T min = std::numeric_limits<T>::min();
|
||||||
|
T max = std::numeric_limits<T>::max();
|
||||||
|
|
||||||
|
variantMin.set(min);
|
||||||
|
variantMax.set(max);
|
||||||
|
|
||||||
|
REQUIRE(min == variantMin.as<T>());
|
||||||
|
REQUIRE(max == variantMax.as<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("JsonVariant set()/get()") {
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
SECTION("SizeOfJsonInteger") {
|
||||||
|
REQUIRE(8 == sizeof(JsonInteger));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SECTION("Null") {
|
||||||
|
checkValue<const char *>(NULL);
|
||||||
|
}
|
||||||
|
SECTION("const char*") {
|
||||||
|
checkValue<const char *>("hello");
|
||||||
|
}
|
||||||
|
SECTION("std::string") {
|
||||||
|
checkValue<std::string>("hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("False") {
|
||||||
|
checkValue<bool>(false);
|
||||||
|
}
|
||||||
|
SECTION("True") {
|
||||||
|
checkValue<bool>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Double") {
|
||||||
|
checkNumericType<double>();
|
||||||
|
}
|
||||||
|
SECTION("Float") {
|
||||||
|
checkNumericType<float>();
|
||||||
|
}
|
||||||
|
SECTION("Char") {
|
||||||
|
checkNumericType<char>();
|
||||||
|
}
|
||||||
|
SECTION("SChar") {
|
||||||
|
checkNumericType<signed char>();
|
||||||
|
}
|
||||||
|
SECTION("SInt") {
|
||||||
|
checkNumericType<signed int>();
|
||||||
|
}
|
||||||
|
SECTION("SLong") {
|
||||||
|
checkNumericType<signed long>();
|
||||||
|
}
|
||||||
|
SECTION("SShort") {
|
||||||
|
checkNumericType<signed short>();
|
||||||
|
}
|
||||||
|
SECTION("UChar") {
|
||||||
|
checkNumericType<unsigned char>();
|
||||||
|
}
|
||||||
|
SECTION("UInt") {
|
||||||
|
checkNumericType<unsigned int>();
|
||||||
|
}
|
||||||
|
SECTION("ULong") {
|
||||||
|
checkNumericType<unsigned long>();
|
||||||
|
}
|
||||||
|
SECTION("UShort") {
|
||||||
|
checkNumericType<unsigned short>();
|
||||||
|
}
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
SECTION("LongLong") {
|
||||||
|
checkNumericType<unsigned long long>();
|
||||||
|
}
|
||||||
|
SECTION("ULongLong") {
|
||||||
|
checkNumericType<unsigned long long>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SECTION("Int8") {
|
||||||
|
checkNumericType<int8_t>();
|
||||||
|
}
|
||||||
|
SECTION("Uint8") {
|
||||||
|
checkNumericType<uint8_t>();
|
||||||
|
}
|
||||||
|
SECTION("Int16") {
|
||||||
|
checkNumericType<int16_t>();
|
||||||
|
}
|
||||||
|
SECTION("Uint16") {
|
||||||
|
checkNumericType<uint16_t>();
|
||||||
|
}
|
||||||
|
SECTION("Int32") {
|
||||||
|
checkNumericType<int32_t>();
|
||||||
|
}
|
||||||
|
SECTION("Uint32") {
|
||||||
|
checkNumericType<uint32_t>();
|
||||||
|
}
|
||||||
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
|
SECTION("Int64") {
|
||||||
|
checkNumericType<int64_t>();
|
||||||
|
}
|
||||||
|
SECTION("Uint64") {
|
||||||
|
checkNumericType<uint64_t>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SECTION("CanStoreObject") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
JsonObject object = doc.to<JsonObject>();
|
||||||
|
|
||||||
|
checkValue<JsonObject>(object);
|
||||||
|
}
|
||||||
|
}
|
12
test/MemberProxy/CMakeLists.txt
Normal file
12
test/MemberProxy/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# ArduinoJson - arduinojson.org
|
||||||
|
# Copyright Benoit Blanchon 2014-2018
|
||||||
|
# MIT License
|
||||||
|
|
||||||
|
add_executable(MemberProxyTests
|
||||||
|
add.cpp
|
||||||
|
subscript.cpp
|
||||||
|
set.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(MemberProxyTests catch)
|
||||||
|
add_test(MemberProxy MemberProxyTests)
|
25
test/MemberProxy/add.cpp
Normal file
25
test/MemberProxy/add.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
|
TEST_CASE("MemberProxy::add()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||||
|
|
||||||
|
SECTION("add(int)") {
|
||||||
|
mp.add(42);
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[42]}");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("add(const char*)") {
|
||||||
|
mp.add("world");
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":[\"world\"]}");
|
||||||
|
}
|
||||||
|
}
|
25
test/MemberProxy/set.cpp
Normal file
25
test/MemberProxy/set.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
|
TEST_CASE("MemberProxy::set()") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||||
|
|
||||||
|
SECTION("set(int)") {
|
||||||
|
mp.set(42);
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":42}");
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("set(const char*)") {
|
||||||
|
mp.set("world");
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":\"world\"}");
|
||||||
|
}
|
||||||
|
}
|
19
test/MemberProxy/subscript.cpp
Normal file
19
test/MemberProxy/subscript.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// ArduinoJson - arduinojson.org
|
||||||
|
// Copyright Benoit Blanchon 2014-2018
|
||||||
|
// MIT License
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
|
|
||||||
|
TEST_CASE("MemberProxy::operator[]") {
|
||||||
|
DynamicJsonDocument doc(4096);
|
||||||
|
MemberProxy<JsonDocument&, const char*> mp = doc["hello"];
|
||||||
|
|
||||||
|
SECTION("set integer") {
|
||||||
|
mp["world"] = 42;
|
||||||
|
|
||||||
|
REQUIRE(doc.as<std::string>() == "{\"hello\":{\"world\":42}}");
|
||||||
|
}
|
||||||
|
}
|
@ -54,10 +54,10 @@ TEST_CASE("Polyfills/type_traits") {
|
|||||||
CHECK(IsVisitable<VariantRef>::value == true);
|
CHECK(IsVisitable<VariantRef>::value == true);
|
||||||
CHECK(IsVisitable<VariantConstRef>::value == true);
|
CHECK(IsVisitable<VariantConstRef>::value == true);
|
||||||
CHECK(IsVisitable<ArrayRef>::value == true);
|
CHECK(IsVisitable<ArrayRef>::value == true);
|
||||||
CHECK(IsVisitable<ArraySubscript>::value == true);
|
CHECK(IsVisitable<ElementProxy<ArrayRef> >::value == true);
|
||||||
CHECK(IsVisitable<ArrayConstRef>::value == true);
|
CHECK(IsVisitable<ArrayConstRef>::value == true);
|
||||||
CHECK(IsVisitable<ObjectRef>::value == true);
|
CHECK(IsVisitable<ObjectRef>::value == true);
|
||||||
CHECK(IsVisitable<ObjectSubscript<const char*> >::value == true);
|
CHECK((IsVisitable<MemberProxy<ObjectRef, const char*> >::value == true));
|
||||||
CHECK(IsVisitable<ObjectConstRef>::value == true);
|
CHECK(IsVisitable<ObjectConstRef>::value == true);
|
||||||
CHECK(IsVisitable<DynamicJsonDocument>::value == true);
|
CHECK(IsVisitable<DynamicJsonDocument>::value == true);
|
||||||
CHECK(IsVisitable<StaticJsonDocument<10> >::value == true);
|
CHECK(IsVisitable<StaticJsonDocument<10> >::value == true);
|
||||||
|
@ -147,7 +147,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonObjectSubscript") {
|
SECTION("MemberProxy") {
|
||||||
SECTION("operator=") { // issue #416
|
SECTION("operator=") { // issue #416
|
||||||
unsigned char value[] = "world";
|
unsigned char value[] = "world";
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ TEST_CASE("unsigned char[]") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JsonArraySubscript") {
|
SECTION("ElementProxy") {
|
||||||
SECTION("set()") {
|
SECTION("set()") {
|
||||||
unsigned char value[] = "world";
|
unsigned char value[] = "world";
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ void check(T value, const std::string &expected) {
|
|||||||
REQUIRE(expected.size() == returnValue);
|
REQUIRE(expected.size() == returnValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("serializeMsgPack(JsonObjectSubscript)") {
|
TEST_CASE("serializeMsgPack(MemberProxy)") {
|
||||||
DynamicJsonDocument doc(4096);
|
DynamicJsonDocument doc(4096);
|
||||||
deserializeJson(doc, "{\"hello\":42}");
|
deserializeJson(doc, "{\"hello\":42}");
|
||||||
JsonObject obj = doc.as<JsonObject>();
|
JsonObject obj = doc.as<JsonObject>();
|
||||||
@ -23,7 +23,7 @@ TEST_CASE("serializeMsgPack(JsonObjectSubscript)") {
|
|||||||
REQUIRE(result == "*");
|
REQUIRE(result == "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("serializeMsgPack(JsonArraySubscript)") {
|
TEST_CASE("serializeMsgPack(ElementProxy)") {
|
||||||
DynamicJsonDocument doc(4096);
|
DynamicJsonDocument doc(4096);
|
||||||
deserializeJson(doc, "[42]");
|
deserializeJson(doc, "[42]");
|
||||||
JsonArray arr = doc.as<JsonArray>();
|
JsonArray arr = doc.as<JsonArray>();
|
||||||
|
Reference in New Issue
Block a user