forked from bblanchon/ArduinoJson
@ -4,9 +4,11 @@ ArduinoJson: change log
|
||||
v5.0 (currently in beta)
|
||||
----
|
||||
|
||||
* Added support of `String` class (issue #55, #56, #70, #77)
|
||||
* Added support of `String` class (issues #55, #56, #70, #77)
|
||||
* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57)
|
||||
* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87)
|
||||
* Added support of non standard JSON input (issue #44)
|
||||
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators
|
||||
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
|
||||
* Switched to new the library layout (requires Arduino 1.0.6 or above)
|
||||
|
||||
**BREAKING CHANGES**:
|
||||
|
@ -23,11 +23,6 @@ inline char const* JsonVariantContent::as<char const*>() const {
|
||||
return asString;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline String JsonVariantContent::as<String>() const {
|
||||
return asString;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline double JsonVariantContent::as<double>() const {
|
||||
return asDouble;
|
||||
|
@ -42,16 +42,46 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
: Internals::List<JsonVariant>(buffer) {}
|
||||
|
||||
// Gets the value at the specified index
|
||||
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
|
||||
FORCE_INLINE JsonVariant operator[](size_t index) const;
|
||||
|
||||
// Gets or sets the value at specified index
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Adds the specified value at the end of the array.
|
||||
FORCE_INLINE bool add(const JsonVariant value);
|
||||
FORCE_INLINE bool add(bool value);
|
||||
FORCE_INLINE bool add(float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool add(double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool add(signed char value);
|
||||
FORCE_INLINE bool add(signed long value);
|
||||
FORCE_INLINE bool add(signed int value);
|
||||
FORCE_INLINE bool add(signed short value);
|
||||
FORCE_INLINE bool add(unsigned char value);
|
||||
FORCE_INLINE bool add(unsigned long value);
|
||||
FORCE_INLINE bool add(unsigned int value);
|
||||
FORCE_INLINE bool add(unsigned short value);
|
||||
FORCE_INLINE bool add(const char *value);
|
||||
FORCE_INLINE bool add(const String &value);
|
||||
FORCE_INLINE bool add(JsonArray &array);
|
||||
FORCE_INLINE bool add(JsonObject &object);
|
||||
FORCE_INLINE bool add(const JsonVariant &object);
|
||||
|
||||
// Sets the value at specified index.
|
||||
FORCE_INLINE void set(size_t index, const JsonVariant value);
|
||||
FORCE_INLINE void set(size_t index, bool value);
|
||||
FORCE_INLINE void set(size_t index, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE void set(size_t index, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE void set(size_t index, signed char value);
|
||||
FORCE_INLINE void set(size_t index, signed long value);
|
||||
FORCE_INLINE void set(size_t index, signed int value);
|
||||
FORCE_INLINE void set(size_t index, signed short value);
|
||||
FORCE_INLINE void set(size_t index, unsigned char value);
|
||||
FORCE_INLINE void set(size_t index, unsigned long value);
|
||||
FORCE_INLINE void set(size_t index, unsigned int value);
|
||||
FORCE_INLINE void set(size_t index, unsigned short value);
|
||||
FORCE_INLINE void set(size_t index, const char *value);
|
||||
FORCE_INLINE void set(size_t index, const String &value);
|
||||
FORCE_INLINE void set(size_t index, JsonArray &array);
|
||||
FORCE_INLINE void set(size_t index, JsonObject &object);
|
||||
FORCE_INLINE void set(size_t index, const JsonVariant &object);
|
||||
|
||||
// Gets the value at the specified index.
|
||||
FORCE_INLINE JsonVariant get(size_t index) const;
|
||||
@ -86,6 +116,15 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
|
||||
private:
|
||||
node_type *getNodeAt(size_t index) const;
|
||||
|
||||
template <typename TValue>
|
||||
void setNodeAt(size_t index, TValue value);
|
||||
|
||||
template <typename TValue>
|
||||
bool addNode(TValue);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeValue(node_type *, T value);
|
||||
|
||||
// The instance returned by JsonArray::invalid()
|
||||
static JsonArray _invalid;
|
||||
};
|
||||
|
@ -15,14 +15,159 @@ inline JsonArraySubscript JsonArray::operator[](size_t index) {
|
||||
return JsonArraySubscript(*this, index);
|
||||
}
|
||||
|
||||
inline const JsonArraySubscript JsonArray::operator[](size_t index) const {
|
||||
return JsonArraySubscript(*const_cast<JsonArray *>(this), index);
|
||||
inline JsonVariant JsonArray::operator[](size_t index) const {
|
||||
return get(index);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const JsonVariant value) {
|
||||
inline bool JsonArray::add(bool value) { return addNode<bool>(value); }
|
||||
|
||||
inline bool JsonArray::add(float value, uint8_t decimals) {
|
||||
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(double value, uint8_t decimals) {
|
||||
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed char value) {
|
||||
return addNode<signed char>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed long value) {
|
||||
return addNode<signed long>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed int value) {
|
||||
return addNode<signed int>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(signed short value) {
|
||||
return addNode<signed short>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned char value) {
|
||||
return addNode<unsigned char>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned long value) {
|
||||
return addNode<unsigned long>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned int value) {
|
||||
return addNode<unsigned int>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(unsigned short value) {
|
||||
return addNode<unsigned short>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const char *value) {
|
||||
return addNode<const char *>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const String &value) {
|
||||
return addNode<const String &>(value);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(JsonArray &array) {
|
||||
return addNode<JsonArray &>(array);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(JsonObject &object) {
|
||||
return addNode<JsonObject &>(object);
|
||||
}
|
||||
|
||||
inline bool JsonArray::add(const JsonVariant &object) {
|
||||
return addNode<const JsonVariant &>(object);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline bool JsonArray::addNode(TValue value) {
|
||||
node_type *node = addNewNode();
|
||||
if (node) node->content = value;
|
||||
return node != NULL;
|
||||
if (node == NULL) return false;
|
||||
setNodeValue<TValue>(node, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, bool value) {
|
||||
return setNodeAt<bool>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, float value, uint8_t decimals) {
|
||||
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, double value, uint8_t decimals) {
|
||||
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed char value) {
|
||||
return setNodeAt<signed char>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed long value) {
|
||||
return setNodeAt<signed long>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed int value) {
|
||||
return setNodeAt<signed int>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, signed short value) {
|
||||
return setNodeAt<signed short>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned char value) {
|
||||
return setNodeAt<unsigned char>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned long value) {
|
||||
return setNodeAt<unsigned long>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned int value) {
|
||||
return setNodeAt<unsigned int>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, unsigned short value) {
|
||||
return setNodeAt<unsigned short>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const char *value) {
|
||||
return setNodeAt<const char *>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const String &value) {
|
||||
return setNodeAt<const String &>(index, value);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, JsonArray &array) {
|
||||
return setNodeAt<JsonArray &>(index, array);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, JsonObject &object) {
|
||||
return setNodeAt<JsonObject &>(index, object);
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const JsonVariant &object) {
|
||||
return setNodeAt<const JsonVariant &>(index, object);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonArray::setNodeAt(size_t index, TValue value) {
|
||||
node_type *node = getNodeAt(index);
|
||||
if (node == NULL) return;
|
||||
setNodeValue<TValue>(node, value);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonArray::setNodeValue(node_type *node, TValue value) {
|
||||
node->content = value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonArray::setNodeValue(node_type *node, const String &value) {
|
||||
node->content = _buffer->strdup(value);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonArray::get(size_t index) const {
|
||||
@ -42,11 +187,6 @@ inline T JsonArray::is(size_t index) const {
|
||||
return node ? node->content.is<T>() : false;
|
||||
}
|
||||
|
||||
inline void JsonArray::set(size_t index, const JsonVariant value) {
|
||||
node_type *node = getNodeAt(index);
|
||||
if (node) node->content = value;
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
|
||||
int index) const {
|
||||
|
@ -6,18 +6,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "JsonSubscriptBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
class JsonArraySubscript : public JsonSubscriptBase<JsonArraySubscript> {
|
||||
public:
|
||||
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
|
||||
: _array(array), _index(index) {}
|
||||
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const JsonVariant& value) {
|
||||
_array.set(_index, value);
|
||||
return *this;
|
||||
}
|
||||
using JsonSubscriptBase::operator=;
|
||||
|
||||
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& other) {
|
||||
// to prevent Visual Studio warning C4512: assignment operator could not be
|
||||
@ -44,13 +41,19 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
|
||||
_array.get(_index).writeTo(writer);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
void set(TValue value) {
|
||||
_array.set(_index, value);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonArray& _array;
|
||||
const size_t _index;
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& os, const JsonArraySubscript& source) {
|
||||
inline std::ostream& operator<<(std::ostream& os,
|
||||
const JsonArraySubscript& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
@ -8,8 +8,10 @@
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t
|
||||
#include <string.h>
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
#include "JsonVariant.hpp"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
@ -59,7 +61,7 @@ class JsonBuffer {
|
||||
|
||||
// Same as above with a String class
|
||||
JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseArray(const_cast<char *>(json.c_str()), nesting);
|
||||
return parseArray(strdup(json), nesting);
|
||||
}
|
||||
|
||||
// Allocates and populate a JsonObject from a JSON string.
|
||||
@ -75,11 +77,15 @@ class JsonBuffer {
|
||||
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);
|
||||
|
||||
// Same as above with a String class
|
||||
JsonObject &parseObject(const String &json,
|
||||
uint8_t nestingLimit = DEFAULT_LIMIT) {
|
||||
return parseObject(const_cast<char *>(json.c_str()), nestingLimit);
|
||||
JsonObject &parseObject(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
|
||||
return parseObject(strdup(json), nesting);
|
||||
}
|
||||
|
||||
// Duplicate a string
|
||||
char *strdup(const char *src) { return strdup(src, strlen(src)); }
|
||||
char *strdup(const String &src) { return strdup(src.c_str(), src.length()); }
|
||||
char *strdup(const char *, size_t);
|
||||
|
||||
// Allocates n bytes in the JsonBuffer.
|
||||
// Return a pointer to the allocated memory or NULL if allocation fails.
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
@ -23,7 +23,6 @@ namespace ArduinoJson {
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonBuffer;
|
||||
class JsonObjectSubscript;
|
||||
|
||||
// A dictionary of JsonVariant indexed by string (char*)
|
||||
//
|
||||
@ -43,13 +42,45 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
: Internals::List<JsonPair>(buffer) {}
|
||||
|
||||
// Gets or sets the value associated with the specified key.
|
||||
FORCE_INLINE JsonObjectSubscript operator[](JsonObjectKey key);
|
||||
FORCE_INLINE JsonObjectSubscript<const char*> operator[](const char* key);
|
||||
FORCE_INLINE JsonObjectSubscript<const String&> operator[](const String& key);
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
FORCE_INLINE const JsonObjectSubscript operator[](JsonObjectKey key) const;
|
||||
FORCE_INLINE JsonVariant operator[](JsonObjectKey key) const;
|
||||
|
||||
// Sets the specified key with the specified value.
|
||||
FORCE_INLINE bool set(JsonObjectKey key, JsonVariant value);
|
||||
FORCE_INLINE bool set(const char* key, bool value);
|
||||
FORCE_INLINE bool set(const char* key, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const char* key, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const char* key, signed char value);
|
||||
FORCE_INLINE bool set(const char* key, signed long value);
|
||||
FORCE_INLINE bool set(const char* key, signed int value);
|
||||
FORCE_INLINE bool set(const char* key, signed short value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned char value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned long value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned int value);
|
||||
FORCE_INLINE bool set(const char* key, unsigned short value);
|
||||
FORCE_INLINE bool set(const char* key, const char* value);
|
||||
FORCE_INLINE bool set(const char* key, const String& value);
|
||||
FORCE_INLINE bool set(const char* key, JsonArray& array);
|
||||
FORCE_INLINE bool set(const char* key, JsonObject& object);
|
||||
FORCE_INLINE bool set(const char* key, const JsonVariant& value);
|
||||
FORCE_INLINE bool set(const String& key, bool value);
|
||||
FORCE_INLINE bool set(const String& key, float value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const String& key, double value, uint8_t decimals = 2);
|
||||
FORCE_INLINE bool set(const String& key, signed char value);
|
||||
FORCE_INLINE bool set(const String& key, signed long value);
|
||||
FORCE_INLINE bool set(const String& key, signed int value);
|
||||
FORCE_INLINE bool set(const String& key, signed short value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned char value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned long value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned int value);
|
||||
FORCE_INLINE bool set(const String& key, unsigned short value);
|
||||
FORCE_INLINE bool set(const String& key, const char* value);
|
||||
FORCE_INLINE bool set(const String& key, const String& value);
|
||||
FORCE_INLINE bool set(const String& key, JsonArray& array);
|
||||
FORCE_INLINE bool set(const String& key, JsonObject& object);
|
||||
FORCE_INLINE bool set(const String& key, const JsonVariant& value);
|
||||
|
||||
// Gets the value associated with the specified key.
|
||||
FORCE_INLINE JsonVariant get(JsonObjectKey) const;
|
||||
@ -64,11 +95,13 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
|
||||
// Creates and adds a JsonArray.
|
||||
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
|
||||
JsonArray& createNestedArray(JsonObjectKey key);
|
||||
FORCE_INLINE JsonArray& createNestedArray(const char* key);
|
||||
FORCE_INLINE JsonArray& createNestedArray(const String& key);
|
||||
|
||||
// Creates and adds a JsonObject.
|
||||
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
|
||||
JsonObject& createNestedObject(JsonObjectKey key);
|
||||
FORCE_INLINE JsonObject& createNestedObject(const char* key);
|
||||
FORCE_INLINE JsonObject& createNestedObject(const String& key);
|
||||
|
||||
// Tells weither the specified key is present and associated with a value.
|
||||
FORCE_INLINE bool containsKey(JsonObjectKey key) const;
|
||||
@ -90,6 +123,21 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
|
||||
|
||||
node_type* getOrCreateNodeAt(JsonObjectKey key);
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
FORCE_INLINE bool setNodeAt(TKey key, TValue value);
|
||||
|
||||
template <typename TKey>
|
||||
JsonArray& createArrayAt(TKey key);
|
||||
|
||||
template <typename TKey>
|
||||
JsonObject& createObjectAt(TKey key);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeKey(node_type*, T key);
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE void setNodeValue(node_type*, T value);
|
||||
|
||||
// The instance returned by JsonObject::invalid()
|
||||
static JsonObject _invalid;
|
||||
};
|
||||
|
@ -28,41 +28,183 @@ inline bool JsonObject::is(JsonObjectKey key) const {
|
||||
return node ? node->content.value.is<T>() : false;
|
||||
}
|
||||
|
||||
inline JsonObjectSubscript JsonObject::operator[](JsonObjectKey key) {
|
||||
return JsonObjectSubscript(*this, key);
|
||||
inline JsonObjectSubscript<const char *> JsonObject::operator[](
|
||||
const char *key) {
|
||||
return JsonObjectSubscript<const char *>(*this, key);
|
||||
}
|
||||
|
||||
inline const JsonObjectSubscript JsonObject::operator[](
|
||||
JsonObjectKey key) const {
|
||||
return JsonObjectSubscript(*const_cast<JsonObject *>(this), key);
|
||||
inline JsonObjectSubscript<const String &> JsonObject::operator[](
|
||||
const String &key) {
|
||||
return JsonObjectSubscript<const String &>(*this, key);
|
||||
}
|
||||
|
||||
inline JsonVariant JsonObject::operator[](JsonObjectKey key) const {
|
||||
return get(key);
|
||||
}
|
||||
|
||||
inline bool JsonObject::containsKey(JsonObjectKey key) const {
|
||||
return getNodeAt(key) != NULL;
|
||||
}
|
||||
|
||||
inline JsonArray &JsonObject::createNestedArray(const char *key) {
|
||||
return createArrayAt<const char *>(key);
|
||||
}
|
||||
|
||||
inline JsonArray &JsonObject::createNestedArray(const String &key) {
|
||||
return createArrayAt<const String &>(key);
|
||||
}
|
||||
|
||||
inline JsonObject &JsonObject::createNestedObject(const char *key) {
|
||||
return createObjectAt<const char *>(key);
|
||||
}
|
||||
|
||||
inline JsonObject &JsonObject::createNestedObject(const String &key) {
|
||||
return createObjectAt<const String &>(key);
|
||||
}
|
||||
|
||||
inline void JsonObject::remove(JsonObjectKey key) {
|
||||
removeNode(getNodeAt(key));
|
||||
}
|
||||
|
||||
inline bool JsonObject::set(JsonObjectKey key, const JsonVariant value) {
|
||||
inline bool JsonObject::set(const char *key, bool value) {
|
||||
return setNodeAt<const char *, bool>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, float value, uint8_t decimals) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, double value, uint8_t decimals) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed char value) {
|
||||
return setNodeAt<const char *, signed char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed long value) {
|
||||
return setNodeAt<const char *, signed long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed int value) {
|
||||
return setNodeAt<const char *, signed int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, signed short value) {
|
||||
return setNodeAt<const char *, signed short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned char value) {
|
||||
return setNodeAt<const char *, unsigned char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned long value) {
|
||||
return setNodeAt<const char *, unsigned long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned int value) {
|
||||
return setNodeAt<const char *, unsigned int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, unsigned short value) {
|
||||
return setNodeAt<const char *, unsigned short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const char *value) {
|
||||
return setNodeAt<const char *, const char *>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const String &value) {
|
||||
return setNodeAt<const char *, const String &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, JsonArray &array) {
|
||||
return setNodeAt<const char *, JsonArray &>(key, array);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, JsonObject &object) {
|
||||
return setNodeAt<const char *, JsonObject &>(key, object);
|
||||
}
|
||||
inline bool JsonObject::set(const char *key, const JsonVariant &value) {
|
||||
return setNodeAt<const char *, const JsonVariant &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, bool value) {
|
||||
return setNodeAt<const String &, bool>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, float value, uint8_t decimals) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, double value, uint8_t decimals) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(
|
||||
key, JsonVariant(value, decimals));
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed char value) {
|
||||
return setNodeAt<const String &, signed char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed long value) {
|
||||
return setNodeAt<const String &, signed long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed int value) {
|
||||
return setNodeAt<const String &, signed int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, signed short value) {
|
||||
return setNodeAt<const String &, signed short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned char value) {
|
||||
return setNodeAt<const String &, unsigned char>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned long value) {
|
||||
return setNodeAt<const String &, unsigned long>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned int value) {
|
||||
return setNodeAt<const String &, unsigned int>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, unsigned short value) {
|
||||
return setNodeAt<const String &, unsigned short>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const char *value) {
|
||||
return setNodeAt<const String &, const char *>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const String &value) {
|
||||
return setNodeAt<const String &, const String &>(key, value);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, JsonArray &array) {
|
||||
return setNodeAt<const String &, JsonArray &>(key, array);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, JsonObject &object) {
|
||||
return setNodeAt<const String &, JsonObject &>(key, object);
|
||||
}
|
||||
inline bool JsonObject::set(const String &key, const JsonVariant &value) {
|
||||
return setNodeAt<const String &, const JsonVariant &>(key, value);
|
||||
}
|
||||
|
||||
template <typename TKey, typename TValue>
|
||||
inline bool JsonObject::setNodeAt(TKey key, TValue value) {
|
||||
node_type *node = getOrCreateNodeAt(key);
|
||||
if (!node) return false;
|
||||
|
||||
node->content.key = key;
|
||||
node->content.value = value;
|
||||
setNodeKey<TKey>(node, key);
|
||||
setNodeValue<TValue>(node, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeKey(node_type *node, const char *key) {
|
||||
node->content.key = key;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeKey(node_type *node, const String &key) {
|
||||
node->content.key = _buffer->strdup(key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
inline void JsonObject::setNodeValue(node_type *node, TValue value) {
|
||||
node->content.value = value;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void JsonObject::setNodeValue(node_type *node, const String &value) {
|
||||
node->content.value = _buffer->strdup(value);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript JsonVariantBase<TImplem>::operator[](
|
||||
const char *key) const {
|
||||
inline const JsonObjectSubscript<const char *> JsonVariantBase<TImplem>::
|
||||
operator[](const char *key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonObjectSubscript JsonVariantBase<TImplem>::operator[](
|
||||
const String &key) const {
|
||||
inline const JsonObjectSubscript<const String &> JsonVariantBase<TImplem>::
|
||||
operator[](const String &key) const {
|
||||
return asObject()[key];
|
||||
}
|
||||
|
||||
|
@ -6,52 +6,64 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantBase.hpp"
|
||||
#include "JsonSubscriptBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript> {
|
||||
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript
|
||||
: public JsonSubscriptBase<JsonObjectSubscript<TKey> > {
|
||||
public:
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject& object, JsonObjectKey key)
|
||||
FORCE_INLINE JsonObjectSubscript(JsonObject& object, TKey key)
|
||||
: _object(object), _key(key) {}
|
||||
|
||||
FORCE_INLINE JsonObjectSubscript& operator=(const JsonVariant& value) {
|
||||
_object.set(_key, value);
|
||||
return *this;
|
||||
}
|
||||
using JsonSubscriptBase<JsonObjectSubscript<TKey> >::operator=;
|
||||
|
||||
FORCE_INLINE JsonObjectSubscript& operator=(
|
||||
const JsonObjectSubscript& other) {
|
||||
FORCE_INLINE JsonObjectSubscript<TKey>& operator=(
|
||||
const JsonObjectSubscript<TKey>& other) {
|
||||
// to prevent Visual Studio warning C4512: assignment operator could not be
|
||||
// generated
|
||||
_object.set(_key, other._object.get(other._key));
|
||||
return *this;
|
||||
return set(other.get());
|
||||
}
|
||||
|
||||
FORCE_INLINE bool success() const { return _object.containsKey(_key); }
|
||||
|
||||
FORCE_INLINE operator JsonVariant() const { return _object.get(_key); }
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE T as() const {
|
||||
return _object.get<T>(_key);
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TValue as() const {
|
||||
return _object.get<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE T is() const {
|
||||
return _object.is<T>(_key);
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TValue is() const {
|
||||
return _object.is<TValue>(_key);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
FORCE_INLINE bool set(TValue value) {
|
||||
return _object.set(_key, value);
|
||||
}
|
||||
|
||||
FORCE_INLINE JsonVariant get() { return _object.get(_key); }
|
||||
|
||||
void writeTo(Internals::JsonWriter& writer) const {
|
||||
_object.get(_key).writeTo(writer);
|
||||
}
|
||||
|
||||
private:
|
||||
JsonObject& _object;
|
||||
JsonObjectKey _key;
|
||||
TKey _key;
|
||||
};
|
||||
|
||||
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& os, const JsonObjectSubscript& source) {
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const String&>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<<(
|
||||
std::ostream& os, const JsonObjectSubscript<const char*>& source) {
|
||||
return source.printTo(os);
|
||||
}
|
||||
#endif
|
||||
|
82
include/ArduinoJson/JsonSubscriptBase.hpp
Normal file
82
include/ArduinoJson/JsonSubscriptBase.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright Benoit Blanchon 2014-2015
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://github.com/bblanchon/ArduinoJson
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantBase.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonSubscriptBase : public JsonVariantBase<TImpl> {
|
||||
public:
|
||||
FORCE_INLINE TImpl& operator=(bool value) { return assign<bool>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(float value) { return assign<float>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(double value) { return assign<double>(value); }
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed char value) {
|
||||
return assign<signed char>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed long value) {
|
||||
return assign<signed long>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed int value) {
|
||||
return assign<signed int>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(signed short value) {
|
||||
return assign<signed short>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned char value) {
|
||||
return assign<unsigned char>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned long value) {
|
||||
return assign<unsigned long>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned int value) {
|
||||
return assign<unsigned int>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(unsigned short value) {
|
||||
return assign<unsigned short>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(const char* value) {
|
||||
return assign<const char*>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(const String& value) {
|
||||
return assign<const String&>(value);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonArray& array) {
|
||||
return assign<JsonArray&>(array);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonObject& object) {
|
||||
return assign<JsonObject&>(object);
|
||||
}
|
||||
|
||||
FORCE_INLINE TImpl& operator=(JsonVariant value) {
|
||||
return assign<JsonVariant>(value);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TValue>
|
||||
FORCE_INLINE TImpl& assign(TValue value) {
|
||||
TImpl* impl = static_cast<TImpl*>(this);
|
||||
impl->template set<TValue>(value);
|
||||
return *impl;
|
||||
}
|
||||
};
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h> // for uint8_t
|
||||
|
||||
#include "Arduino/String.hpp"
|
||||
#include "Internals/JsonPrintable.hpp"
|
||||
#include "Internals/JsonVariantContent.hpp"
|
||||
#include "Internals/JsonVariantType.hpp"
|
||||
@ -55,7 +54,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
||||
|
||||
// Create a JsonVariant containing a string.
|
||||
FORCE_INLINE JsonVariant(const char *value);
|
||||
FORCE_INLINE JsonVariant(const String &value);
|
||||
|
||||
// Create a JsonVariant containing a reference to an array.
|
||||
FORCE_INLINE JsonVariant(JsonArray &array);
|
||||
|
@ -20,11 +20,6 @@ inline JsonVariant::JsonVariant(const char *value) {
|
||||
_content.asString = value;
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(const String &value) {
|
||||
_type = Internals::JSON_STRING;
|
||||
_content.asString = value.c_str();
|
||||
}
|
||||
|
||||
inline JsonVariant::JsonVariant(double value, uint8_t decimals) {
|
||||
_type = static_cast<Internals::JsonVariantType>(
|
||||
Internals::JSON_DOUBLE_0_DECIMALS + decimals);
|
||||
@ -112,11 +107,6 @@ inline bool JsonVariant::is<char const *>() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<String>() const {
|
||||
return _type == Internals::JSON_STRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JsonVariant::is<double>() const {
|
||||
return _type >= Internals::JSON_DOUBLE_0_DECIMALS;
|
||||
|
@ -13,6 +13,7 @@ namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
@ -76,8 +77,10 @@ class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
FORCE_INLINE const JsonObjectSubscript operator[](const char *key) const;
|
||||
FORCE_INLINE const JsonObjectSubscript operator[](const String &key) const;
|
||||
FORCE_INLINE const JsonObjectSubscript<const char *> operator[](
|
||||
const char *key) const;
|
||||
FORCE_INLINE const JsonObjectSubscript<const String &> operator[](
|
||||
const String &key) const;
|
||||
|
||||
// Serialize the variant to a JsonWriter
|
||||
void writeTo(Internals::JsonWriter &writer) const;
|
||||
|
@ -49,7 +49,7 @@ size_t DynamicJsonBuffer::size() const {
|
||||
}
|
||||
|
||||
void* DynamicJsonBuffer::alloc(size_t bytes) {
|
||||
if (!canAllocInHead(bytes)) addNewBlock();
|
||||
while (!canAllocInHead(bytes)) addNewBlock();
|
||||
return allocInHead(bytes);
|
||||
}
|
||||
|
||||
|
@ -32,3 +32,10 @@ JsonObject &JsonBuffer::parseObject(char *json, uint8_t nestingLimit) {
|
||||
JsonParser parser(this, json, nestingLimit);
|
||||
return parser.parseObject();
|
||||
}
|
||||
|
||||
char *JsonBuffer::strdup(const char *source, size_t length) {
|
||||
size_t size = length + 1;
|
||||
char *dest = static_cast<char *>(alloc(size));
|
||||
if (dest != NULL) memcpy(dest, source, size);
|
||||
return dest;
|
||||
}
|
||||
|
@ -25,19 +25,25 @@ JsonObject::node_type *JsonObject::getOrCreateNodeAt(JsonObjectKey key) {
|
||||
return newNode;
|
||||
}
|
||||
|
||||
JsonArray &JsonObject::createNestedArray(JsonObjectKey key) {
|
||||
template <typename TKey>
|
||||
JsonArray &JsonObject::createArrayAt(TKey key) {
|
||||
if (!_buffer) return JsonArray::invalid();
|
||||
JsonArray &array = _buffer->createArray();
|
||||
set(key, array);
|
||||
setNodeAt<TKey, const JsonVariant &>(key, array);
|
||||
return array;
|
||||
}
|
||||
template JsonArray &JsonObject::createArrayAt<const char *>(const char *);
|
||||
template JsonArray &JsonObject::createArrayAt<const String &>(const String &);
|
||||
|
||||
JsonObject &JsonObject::createNestedObject(JsonObjectKey key) {
|
||||
template <typename TKey>
|
||||
JsonObject &JsonObject::createObjectAt(TKey key) {
|
||||
if (!_buffer) return JsonObject::invalid();
|
||||
JsonObject &object = _buffer->createObject();
|
||||
set(key, object);
|
||||
return object;
|
||||
JsonObject &array = _buffer->createObject();
|
||||
setNodeAt<TKey, const JsonVariant &>(key, array);
|
||||
return array;
|
||||
}
|
||||
template JsonObject &JsonObject::createObjectAt<const char *>(const char *);
|
||||
template JsonObject &JsonObject::createObjectAt<const String &>(const String &);
|
||||
|
||||
JsonObject::node_type *JsonObject::getNodeAt(JsonObjectKey key) const {
|
||||
for (node_type *node = _firstNode; node; node = node->next) {
|
||||
|
@ -7,103 +7,160 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(ArduinoStringTests, JsonBuffer_ParseArray) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
String json("[1,2]");
|
||||
JsonArray &array = jsonBuffer.parseArray(json);
|
||||
class ArduinoStringTests : public ::testing::Test {
|
||||
protected:
|
||||
static void eraseString(String &str) {
|
||||
char *p = const_cast<char *>(str.c_str());
|
||||
while (*p) *p++ = '*';
|
||||
}
|
||||
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
};
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseArray) {
|
||||
String json("[\"hello\"]");
|
||||
JsonArray &array = _jsonBuffer.parseArray(json);
|
||||
eraseString(json);
|
||||
ASSERT_TRUE(array.success());
|
||||
ASSERT_STREQ("hello", array[0]);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonBuffer_ParseObject) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
String json("{\"a\":1,\"b\":2}");
|
||||
JsonObject &object = jsonBuffer.parseObject(json);
|
||||
TEST_F(ArduinoStringTests, JsonBuffer_ParseObject) {
|
||||
String json("{\"hello\":\"world\"}");
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
eraseString(json);
|
||||
ASSERT_TRUE(object.success());
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonVariant) {
|
||||
String input = "Hello world!";
|
||||
JsonVariant variant(input);
|
||||
ASSERT_TRUE(variant.is<String>());
|
||||
String output = variant.as<String>();
|
||||
ASSERT_EQ(input, output);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_Subscript) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_Subscript) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
JsonObject &object = jsonBuffer.parseObject(json);
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object[String("key")]);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_ConstSubscript) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_ConstSubscript) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = jsonBuffer.parseObject(json);
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object[String("key")]);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_Set) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
JsonObject &object = jsonBuffer.createObject();
|
||||
String key = "key";
|
||||
object.set(key, "value");
|
||||
ASSERT_STREQ("value", object["key"]);
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetKey) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
object.set(key, "world");
|
||||
eraseString(key);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_Get) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String value("world");
|
||||
object.set("hello", value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_SetKeyValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
String value("world");
|
||||
object.set(key, value);
|
||||
eraseString(key);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObject_Get) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = jsonBuffer.parseObject(json);
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object.get(String("key")));
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_GetT) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_GetT) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = jsonBuffer.parseObject(json);
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_STREQ("value", object.get<const char *>(String("key")));
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_IsT) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_IsT) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = jsonBuffer.parseObject(json);
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_TRUE(object.is<const char *>(String("key")));
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_CreateNestedObject) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_CreateNestedObject) {
|
||||
String key = "key";
|
||||
char json[64];
|
||||
JsonObject &object = jsonBuffer.createObject();
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.createNestedObject(key);
|
||||
eraseString(key);
|
||||
object.printTo(json, sizeof(json));
|
||||
ASSERT_STREQ("{\"key\":{}}", json);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_CreateNestedArray) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_CreateNestedArray) {
|
||||
String key = "key";
|
||||
char json[64];
|
||||
JsonObject &object = jsonBuffer.createObject();
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
object.createNestedArray(key);
|
||||
eraseString(key);
|
||||
object.printTo(json, sizeof(json));
|
||||
ASSERT_STREQ("{\"key\":[]}", json);
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_ContainsKey) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_ContainsKey) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
const JsonObject &object = jsonBuffer.parseObject(json);
|
||||
const JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_TRUE(object.containsKey(String("key")));
|
||||
}
|
||||
|
||||
TEST(ArduinoStringTests, JsonObject_Remove) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
TEST_F(ArduinoStringTests, JsonObject_Remove) {
|
||||
char json[] = "{\"key\":\"value\"}";
|
||||
JsonObject &object = jsonBuffer.parseObject(json);
|
||||
JsonObject &object = _jsonBuffer.parseObject(json);
|
||||
ASSERT_EQ(1, object.size());
|
||||
object.remove(String("key"));
|
||||
ASSERT_EQ(0, object.size());
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetKey) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String key("hello");
|
||||
object[key] = "world";
|
||||
eraseString(key);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonObjectSubscript_SetValue) {
|
||||
JsonObject &object = _jsonBuffer.createObject();
|
||||
String value("world");
|
||||
object["hello"] = value;
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", object["hello"]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_Add) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("hello");
|
||||
array.add(value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("hello", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArray_Set) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("world");
|
||||
array.add("hello");
|
||||
array.set(0, value);
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", array[0]);
|
||||
}
|
||||
|
||||
TEST_F(ArduinoStringTests, JsonArraySubscript) {
|
||||
JsonArray &array = _jsonBuffer.createArray();
|
||||
String value("world");
|
||||
array.add("hello");
|
||||
array[0] = value;
|
||||
eraseString(value);
|
||||
ASSERT_STREQ("world", array[0]);
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ TEST_F(JsonObject_Container_Tests,
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreIntegers) {
|
||||
_object["hello"] = 123;
|
||||
_object["world"] = 456;
|
||||
_object.set("world", 456);
|
||||
|
||||
EXPECT_EQ(123, _object["hello"].as<int>());
|
||||
EXPECT_EQ(456, _object["world"].as<int>());
|
||||
@ -67,7 +67,7 @@ TEST_F(JsonObject_Container_Tests, CanStoreIntegers) {
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreDoubles) {
|
||||
_object["hello"] = 123.45;
|
||||
_object["world"] = 456.78;
|
||||
_object.set("world", 456.78);
|
||||
|
||||
EXPECT_EQ(123.45, _object["hello"].as<double>());
|
||||
EXPECT_EQ(456.78, _object["world"].as<double>());
|
||||
@ -75,7 +75,7 @@ TEST_F(JsonObject_Container_Tests, CanStoreDoubles) {
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreBooleans) {
|
||||
_object["hello"] = true;
|
||||
_object["world"] = false;
|
||||
_object.set("world", false);
|
||||
|
||||
EXPECT_TRUE(_object["hello"].as<bool>());
|
||||
EXPECT_FALSE(_object["world"].as<bool>());
|
||||
@ -83,32 +83,32 @@ TEST_F(JsonObject_Container_Tests, CanStoreBooleans) {
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreStrings) {
|
||||
_object["hello"] = "h3110";
|
||||
_object["world"] = "w0r1d";
|
||||
_object.set("world", "w0r1d");
|
||||
|
||||
EXPECT_STREQ("h3110", _object["hello"].as<const char*>());
|
||||
EXPECT_STREQ("w0r1d", _object["world"].as<const char*>());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreInnerArrays) {
|
||||
JsonArray& innerarray1 = _jsonBuffer.createArray();
|
||||
JsonArray& innerarray2 = _jsonBuffer.createArray();
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreArrays) {
|
||||
JsonArray& array1 = _jsonBuffer.createArray();
|
||||
JsonArray& array2 = _jsonBuffer.createArray();
|
||||
|
||||
_object["hello"] = innerarray1;
|
||||
_object["world"] = innerarray2;
|
||||
_object["hello"] = array1;
|
||||
_object.set("world", array2);
|
||||
|
||||
EXPECT_EQ(&innerarray1, &_object["hello"].asArray());
|
||||
EXPECT_EQ(&innerarray2, &_object["world"].asArray());
|
||||
EXPECT_EQ(&array1, &_object["hello"].asArray());
|
||||
EXPECT_EQ(&array2, &_object["world"].asArray());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreInnerObjects) {
|
||||
JsonObject& innerObject1 = _jsonBuffer.createObject();
|
||||
JsonObject& innerObject2 = _jsonBuffer.createObject();
|
||||
TEST_F(JsonObject_Container_Tests, CanStoreObjects) {
|
||||
JsonObject& object1 = _jsonBuffer.createObject();
|
||||
JsonObject& object2 = _jsonBuffer.createObject();
|
||||
|
||||
_object["hello"] = innerObject1;
|
||||
_object["world"] = innerObject2;
|
||||
_object["hello"] = object1;
|
||||
_object.set("world", object2);
|
||||
|
||||
EXPECT_EQ(&innerObject1, &_object["hello"].asObject());
|
||||
EXPECT_EQ(&innerObject2, &_object["world"].asObject());
|
||||
EXPECT_EQ(&object1, &_object["hello"].asObject());
|
||||
EXPECT_EQ(&object2, &_object["world"].asObject());
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_Container_Tests, ContainsKeyReturnsFalseForNonExistingKey) {
|
||||
|
@ -11,131 +11,105 @@ using namespace ArduinoJson::Internals;
|
||||
|
||||
class JsonObject_PrintTo_Tests : public testing::Test {
|
||||
public:
|
||||
JsonObject_PrintTo_Tests() : object(json.createObject()) {}
|
||||
JsonObject_PrintTo_Tests() : _object(_jsonBuffer.createObject()) {}
|
||||
|
||||
protected:
|
||||
void outputMustBe(const char *expected) {
|
||||
char actual[256];
|
||||
size_t actualLen = object.printTo(actual, sizeof(actual));
|
||||
size_t measuredLen = object.measureLength();
|
||||
size_t actualLen = _object.printTo(actual, sizeof(actual));
|
||||
size_t measuredLen = _object.measureLength();
|
||||
|
||||
EXPECT_STREQ(expected, actual);
|
||||
EXPECT_EQ(strlen(expected), actualLen);
|
||||
EXPECT_EQ(strlen(expected), measuredLen);
|
||||
}
|
||||
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(2)> json;
|
||||
JsonObject &object;
|
||||
DynamicJsonBuffer _jsonBuffer;
|
||||
JsonObject &_object;
|
||||
};
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, EmptyObject) { outputMustBe("{}"); }
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneString) {
|
||||
object["key"] = "value";
|
||||
|
||||
outputMustBe("{\"key\":\"value\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, TwoStrings) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
_object["key1"] = "value1";
|
||||
_object.set("key2", "value2");
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, RemoveFirst) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key1");
|
||||
_object["key1"] = "value1";
|
||||
_object["key2"] = "value2";
|
||||
_object.remove("key1");
|
||||
|
||||
outputMustBe("{\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, RemoveLast) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key2");
|
||||
_object["key1"] = "value1";
|
||||
_object["key2"] = "value2";
|
||||
_object.remove("key2");
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, RemoveUnexistingKey) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object.remove("key3");
|
||||
_object["key1"] = "value1";
|
||||
_object["key2"] = "value2";
|
||||
_object.remove("key3");
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, ReplaceExistingKey) {
|
||||
object["key"] = "value1";
|
||||
object["key"] = "value2";
|
||||
_object["key"] = "value1";
|
||||
_object["key"] = "value2";
|
||||
|
||||
outputMustBe("{\"key\":\"value2\"}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneStringOverCapacity) {
|
||||
object["key1"] = "value1";
|
||||
object["key2"] = "value2";
|
||||
object["key3"] = "value3";
|
||||
|
||||
outputMustBe("{\"key1\":\"value1\",\"key2\":\"value2\"}");
|
||||
TEST_F(JsonObject_PrintTo_Tests, TwoIntegers) {
|
||||
_object["a"] = 1;
|
||||
_object.set("b", 2);
|
||||
outputMustBe("{\"a\":1,\"b\":2}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneInteger) {
|
||||
object["key"] = 1;
|
||||
outputMustBe("{\"key\":1}");
|
||||
TEST_F(JsonObject_PrintTo_Tests, TwoDoublesFourDigits) {
|
||||
_object["a"] = double_with_n_digits(3.14159265358979323846, 4);
|
||||
_object.set("b", 2.71828182845904523536, 4);
|
||||
outputMustBe("{\"a\":3.1416,\"b\":2.7183}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneDoubleFourDigits) {
|
||||
object["key"] = double_with_n_digits(3.14159265358979323846, 4);
|
||||
outputMustBe("{\"key\":3.1416}");
|
||||
TEST_F(JsonObject_PrintTo_Tests, TwoDoubleDefaultDigits) {
|
||||
_object["a"] = 3.14159265358979323846;
|
||||
_object.set("b", 2.71828182845904523536);
|
||||
outputMustBe("{\"a\":3.14,\"b\":2.72}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneDoubleDefaultDigits) {
|
||||
object["key"] = 3.14159265358979323846;
|
||||
outputMustBe("{\"key\":3.14}");
|
||||
TEST_F(JsonObject_PrintTo_Tests, TwoNull) {
|
||||
_object["a"] = static_cast<char *>(0);
|
||||
_object.set("b", static_cast<char *>(0));
|
||||
outputMustBe("{\"a\":null,\"b\":null}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneNull) {
|
||||
object["key"] = static_cast<char *>(0);
|
||||
outputMustBe("{\"key\":null}");
|
||||
TEST_F(JsonObject_PrintTo_Tests, TwoBooleans) {
|
||||
_object["a"] = true;
|
||||
_object.set("b", false);
|
||||
outputMustBe("{\"a\":true,\"b\":false}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneTrue) {
|
||||
object["key"] = true;
|
||||
outputMustBe("{\"key\":true}");
|
||||
TEST_F(JsonObject_PrintTo_Tests, ThreeNestedArrays) {
|
||||
_object.createNestedArray("a");
|
||||
_object["b"] = _jsonBuffer.createArray();
|
||||
_object.set("c", _jsonBuffer.createArray());
|
||||
|
||||
outputMustBe("{\"a\":[],\"b\":[],\"c\":[]}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneFalse) {
|
||||
object["key"] = false;
|
||||
outputMustBe("{\"key\":false}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedArrayViaProxy) {
|
||||
JsonArray &nestedArray = json.createArray();
|
||||
|
||||
object["key"] = nestedArray;
|
||||
|
||||
outputMustBe("{\"key\":[]}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedObjectViaProxy) {
|
||||
JsonObject &nestedArray = json.createObject();
|
||||
|
||||
object["key"] = nestedArray;
|
||||
|
||||
outputMustBe("{\"key\":{}}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedObject) {
|
||||
object.createNestedObject("key");
|
||||
|
||||
outputMustBe("{\"key\":{}}");
|
||||
}
|
||||
|
||||
TEST_F(JsonObject_PrintTo_Tests, OneEmptyNestedArray) {
|
||||
object.createNestedArray("key");
|
||||
|
||||
outputMustBe("{\"key\":[]}");
|
||||
TEST_F(JsonObject_PrintTo_Tests, ThreeNestedObjects) {
|
||||
_object.createNestedObject("a");
|
||||
_object["b"] = _jsonBuffer.createObject();
|
||||
_object.set("c", _jsonBuffer.createObject());
|
||||
|
||||
outputMustBe("{\"a\":{},\"b\":{},\"c\":{}}");
|
||||
}
|
||||
|
@ -8,44 +8,49 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
TEST(StaticJsonBuffer_CreateObject_Tests, GrowsWithObject) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> json;
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(3)> buffer;
|
||||
|
||||
JsonObject &obj = json.createObject();
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size());
|
||||
JsonObject &obj = buffer.createObject();
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(0), buffer.size());
|
||||
|
||||
obj["hello"];
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(0), json.size());
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(0), buffer.size());
|
||||
|
||||
obj["hello"] = 1;
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(1), buffer.size());
|
||||
|
||||
obj["world"] = 2;
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), buffer.size());
|
||||
|
||||
obj["world"] = 3; // <- same key, should not grow
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), json.size());
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(2), buffer.size());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_CreateObject_Tests, SucceedWhenBigEnough) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> json;
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(0)> buffer;
|
||||
|
||||
JsonObject &object = json.createObject();
|
||||
JsonObject &object = buffer.createObject();
|
||||
ASSERT_TRUE(object.success());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_CreateObject_Tests, FailsWhenTooSmall) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> json;
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(0) - 1> buffer;
|
||||
|
||||
JsonObject &object = json.createObject();
|
||||
JsonObject &object = buffer.createObject();
|
||||
ASSERT_FALSE(object.success());
|
||||
}
|
||||
|
||||
TEST(StaticJsonBuffer_CreateObject_Tests, ObjectDoesntGrowWhenFull) {
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> json;
|
||||
StaticJsonBuffer<JSON_OBJECT_SIZE(1)> buffer;
|
||||
|
||||
JsonObject &obj = json.createObject();
|
||||
JsonObject &obj = buffer.createObject();
|
||||
obj["hello"] = 1;
|
||||
obj["world"] = 2;
|
||||
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(1), json.size());
|
||||
ASSERT_EQ(JSON_OBJECT_SIZE(1), buffer.size());
|
||||
ASSERT_EQ(1, obj.size());
|
||||
|
||||
char json[64];
|
||||
obj.printTo(json, sizeof(json));
|
||||
ASSERT_STREQ("{\"hello\":1}", json);
|
||||
}
|
||||
|
Reference in New Issue
Block a user