JsonObject.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright Benoit Blanchon 2014-2016
  2. // MIT License
  3. //
  4. // Arduino JSON library
  5. // https://github.com/bblanchon/ArduinoJson
  6. // If you like this project, please add a star!
  7. #pragma once
  8. #include "String.hpp"
  9. #include "Internals/JsonBufferAllocated.hpp"
  10. #include "Internals/JsonPrintable.hpp"
  11. #include "Internals/List.hpp"
  12. #include "Internals/ReferenceType.hpp"
  13. #include "JsonPair.hpp"
  14. #include "TypeTraits/EnableIf.hpp"
  15. #include "TypeTraits/IsFloatingPoint.hpp"
  16. #include "TypeTraits/IsReference.hpp"
  17. #include "TypeTraits/IsSame.hpp"
  18. // Returns the size (in bytes) of an object with n elements.
  19. // Can be very handy to determine the size of a StaticJsonBuffer.
  20. #define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
  21. (sizeof(JsonObject) + (NUMBER_OF_ELEMENTS) * sizeof(JsonObject::node_type))
  22. namespace ArduinoJson {
  23. // Forward declarations
  24. class JsonArray;
  25. class JsonBuffer;
  26. // A dictionary of JsonVariant indexed by string (char*)
  27. //
  28. // The constructor is private, instances must be created via
  29. // JsonBuffer::createObject() or JsonBuffer::parseObject().
  30. // A JsonObject can be serialized to a JSON string via JsonObject::printTo().
  31. // It can also be deserialized from a JSON string via JsonBuffer::parseObject().
  32. class JsonObject : public Internals::JsonPrintable<JsonObject>,
  33. public Internals::ReferenceType,
  34. public Internals::List<JsonPair>,
  35. public Internals::JsonBufferAllocated {
  36. public:
  37. // A meta-function that returns true if type T can be used in
  38. // JsonObject::set()
  39. template <typename T>
  40. struct CanSet {
  41. static const bool value = JsonVariant::IsConstructibleFrom<T>::value ||
  42. TypeTraits::IsSame<T, String&>::value ||
  43. TypeTraits::IsSame<T, const String&>::value;
  44. };
  45. // Create an empty JsonArray attached to the specified JsonBuffer.
  46. // You should not use this constructor directly.
  47. // Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
  48. explicit JsonObject(JsonBuffer* buffer) : Internals::List<JsonPair>(buffer) {}
  49. // Gets or sets the value associated with the specified key.
  50. JsonObjectSubscript<const char*> operator[](const char* key);
  51. JsonObjectSubscript<const String&> operator[](const String& key);
  52. // Gets the value associated with the specified key.
  53. JsonVariant operator[](JsonObjectKey key) const {
  54. return get(key);
  55. }
  56. // Sets the specified key with the specified value.
  57. // bool set(TKey key, bool value);
  58. // bool set(TKey key, char value);
  59. // bool set(TKey key, long value);
  60. // bool set(TKey key, int value);
  61. // bool set(TKey key, short value);
  62. // bool set(TKey key, float value);
  63. // bool set(TKey key, double value);
  64. // bool set(TKey key, const char* value);
  65. // bool set(TKey key, RawJson value);
  66. template <typename T>
  67. bool set(
  68. JsonObjectKey key, T value,
  69. typename TypeTraits::EnableIf<
  70. CanSet<T>::value && !TypeTraits::IsReference<T>::value>::type* = 0) {
  71. return setNodeAt<T>(key, value);
  72. }
  73. // bool set(Key, String&);
  74. // bool set(Key, JsonArray&);
  75. // bool set(Key, JsonObject&);
  76. // bool set(Key, JsonVariant&);
  77. template <typename T>
  78. bool set(JsonObjectKey key, const T& value,
  79. typename TypeTraits::EnableIf<CanSet<T&>::value>::type* = 0) {
  80. return setNodeAt<T&>(key, const_cast<T&>(value));
  81. }
  82. // bool set(Key, float value, uint8_t decimals);
  83. // bool set(Key, double value, uint8_t decimals);
  84. template <typename TValue>
  85. bool set(JsonObjectKey key, TValue value, uint8_t decimals,
  86. typename TypeTraits::EnableIf<
  87. TypeTraits::IsFloatingPoint<TValue>::value>::type* = 0) {
  88. return setNodeAt<const JsonVariant&>(key, JsonVariant(value, decimals));
  89. }
  90. // Gets the value associated with the specified key.
  91. JsonVariant get(JsonObjectKey key) const {
  92. node_type* node = getNodeAt(key.c_str());
  93. return node ? node->content.value : JsonVariant();
  94. }
  95. // Gets the value associated with the specified key.
  96. template <typename T>
  97. typename Internals::JsonVariantAs<T>::type get(JsonObjectKey key) const {
  98. node_type* node = getNodeAt(key.c_str());
  99. return node ? node->content.value.as<T>() : JsonVariant::defaultValue<T>();
  100. }
  101. // Checks the type of the value associated with the specified key.
  102. template <typename T>
  103. bool is(JsonObjectKey key) const {
  104. node_type* node = getNodeAt(key.c_str());
  105. return node ? node->content.value.is<T>() : false;
  106. }
  107. // Creates and adds a JsonArray.
  108. // This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
  109. JsonArray& createNestedArray(JsonObjectKey key);
  110. // Creates and adds a JsonObject.
  111. // This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
  112. JsonObject& createNestedObject(JsonObjectKey key);
  113. // Tells weither the specified key is present and associated with a value.
  114. bool containsKey(JsonObjectKey key) const {
  115. return getNodeAt(key.c_str()) != NULL;
  116. }
  117. // Removes the specified key and the associated value.
  118. void remove(JsonObjectKey key) {
  119. removeNode(getNodeAt(key.c_str()));
  120. }
  121. // Returns a reference an invalid JsonObject.
  122. // This object is meant to replace a NULL pointer.
  123. // This is used when memory allocation or JSON parsing fail.
  124. static JsonObject& invalid() {
  125. static JsonObject instance(NULL);
  126. return instance;
  127. }
  128. // Serialize the object to the specified JsonWriter
  129. void writeTo(Internals::JsonWriter& writer) const {
  130. writer.beginObject();
  131. const node_type* node = _firstNode;
  132. while (node) {
  133. writer.writeString(node->content.key);
  134. writer.writeColon();
  135. node->content.value.writeTo(writer);
  136. node = node->next;
  137. if (!node) break;
  138. writer.writeComma();
  139. }
  140. writer.endObject();
  141. }
  142. private:
  143. // Returns the list node that matches the specified key.
  144. node_type* getNodeAt(const char* key) const {
  145. for (node_type* node = _firstNode; node; node = node->next) {
  146. if (!strcmp(node->content.key, key)) return node;
  147. }
  148. return NULL;
  149. }
  150. template <typename T>
  151. bool setNodeAt(JsonObjectKey key, T value) {
  152. node_type* node = getNodeAt(key.c_str());
  153. if (!node) {
  154. node = addNewNode();
  155. if (!node || !setNodeKey(node, key)) return false;
  156. }
  157. return setNodeValue<T>(node, value);
  158. }
  159. bool setNodeKey(node_type* node, JsonObjectKey key) {
  160. if (key.needs_copy()) {
  161. node->content.key = _buffer->strdup(key.c_str());
  162. if (node->content.key == NULL) return false;
  163. } else {
  164. node->content.key = key.c_str();
  165. }
  166. return true;
  167. }
  168. template <typename T>
  169. bool setNodeValue(node_type* node, T value) {
  170. node->content.value = value;
  171. return true;
  172. }
  173. };
  174. }