JsonVariant.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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 <stddef.h>
  9. #include <stdint.h> // for uint8_t
  10. #include "Internals/JsonPrintable.hpp"
  11. #include "Internals/JsonVariantContent.hpp"
  12. #include "Internals/JsonVariantType.hpp"
  13. #include "JsonVariantBase.hpp"
  14. #include "RawJson.hpp"
  15. #include "TypeTraits/EnableIf.hpp"
  16. #include "TypeTraits/IsFloatingPoint.hpp"
  17. #include "TypeTraits/IsIntegral.hpp"
  18. #include "TypeTraits/IsSame.hpp"
  19. #include "TypeTraits/RemoveConst.hpp"
  20. #include "TypeTraits/RemoveReference.hpp"
  21. namespace ArduinoJson {
  22. // Forward declarations.
  23. class JsonArray;
  24. class JsonObject;
  25. // A variant that can be a any value serializable to a JSON value.
  26. //
  27. // It can be set to:
  28. // - a boolean
  29. // - a char, short, int or a long (signed or unsigned)
  30. // - a string (const char*)
  31. // - a reference to a JsonArray or JsonObject
  32. class JsonVariant : public JsonVariantBase<JsonVariant> {
  33. public:
  34. template <typename T>
  35. struct IsConstructibleFrom;
  36. // Creates an uninitialized JsonVariant
  37. JsonVariant() : _type(Internals::JSON_UNDEFINED) {}
  38. // Create a JsonVariant containing a boolean value.
  39. // It will be serialized as "true" or "false" in JSON.
  40. JsonVariant(bool value) {
  41. using namespace Internals;
  42. _type = JSON_BOOLEAN;
  43. _content.asInteger = static_cast<JsonInteger>(value);
  44. }
  45. // Create a JsonVariant containing a floating point value.
  46. // The second argument specifies the number of decimal digits to write in
  47. // the JSON string.
  48. // JsonVariant(double value, uint8_t decimals);
  49. // JsonVariant(float value, uint8_t decimals);
  50. template <typename T>
  51. JsonVariant(T value, uint8_t decimals = 2,
  52. typename TypeTraits::EnableIf<
  53. TypeTraits::IsFloatingPoint<T>::value>::type * = 0) {
  54. using namespace Internals;
  55. _type = static_cast<JsonVariantType>(JSON_FLOAT_0_DECIMALS + decimals);
  56. _content.asFloat = static_cast<JsonFloat>(value);
  57. }
  58. // Create a JsonVariant containing an integer value.
  59. // JsonVariant(signed short)
  60. // JsonVariant(signed int)
  61. // JsonVariant(signed long)
  62. template <typename T>
  63. JsonVariant(T value,
  64. typename TypeTraits::EnableIf<
  65. TypeTraits::IsSignedIntegral<T>::value>::type * = 0) {
  66. using namespace Internals;
  67. if (value >= 0) {
  68. _type = JSON_POSITIVE_INTEGER;
  69. _content.asInteger = static_cast<JsonUInt>(value);
  70. } else {
  71. _type = JSON_NEGATIVE_INTEGER;
  72. _content.asInteger = static_cast<JsonUInt>(-value);
  73. }
  74. }
  75. // JsonVariant(unsigned short)
  76. // JsonVariant(unsigned int)
  77. // JsonVariant(unsigned long)
  78. template <typename T>
  79. JsonVariant(T value,
  80. typename TypeTraits::EnableIf<
  81. TypeTraits::IsUnsignedIntegral<T>::value>::type * = 0) {
  82. using namespace Internals;
  83. _type = JSON_POSITIVE_INTEGER;
  84. _content.asInteger = static_cast<JsonUInt>(value);
  85. }
  86. // Create a JsonVariant containing a string.
  87. JsonVariant(const char *value) {
  88. _type = Internals::JSON_STRING;
  89. _content.asString = value;
  90. }
  91. // Create a JsonVariant containing an unparsed string
  92. JsonVariant(RawJson value) {
  93. _type = Internals::JSON_UNPARSED;
  94. _content.asString = value;
  95. }
  96. // Create a JsonVariant containing a reference to an array.
  97. JsonVariant(JsonArray &array) {
  98. _type = Internals::JSON_ARRAY;
  99. _content.asArray = &array;
  100. }
  101. // Create a JsonVariant containing a reference to an object.
  102. JsonVariant(JsonObject &object) {
  103. _type = Internals::JSON_OBJECT;
  104. _content.asObject = &object;
  105. }
  106. // Get the variant as the specified type.
  107. //
  108. // short as<signed short>() const;
  109. // int as<signed int>() const;
  110. // long as<signed long>() const;
  111. template <typename T>
  112. const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value,
  113. T>::type
  114. as() const {
  115. return static_cast<T>(asInteger());
  116. }
  117. //
  118. // short as<unsigned short>() const;
  119. // int as<unsigned int>() const;
  120. // long as<unsigned long>() const;
  121. template <typename T>
  122. const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value,
  123. T>::type
  124. as() const {
  125. return static_cast<T>(asUnsignedInteger());
  126. }
  127. //
  128. // double as<double>() const;
  129. // float as<float>() const;
  130. template <typename T>
  131. const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
  132. T>::type
  133. as() const {
  134. return static_cast<T>(asFloat());
  135. }
  136. //
  137. // const String as<String>() const;
  138. template <typename T>
  139. const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, String>::value,
  140. T>::type
  141. as() const {
  142. return toString();
  143. }
  144. //
  145. // const char* as<const char*>() const;
  146. // const char* as<char*>() const;
  147. template <typename T>
  148. typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
  149. TypeTraits::IsSame<T, char *>::value,
  150. const char *>::type
  151. as() const {
  152. return asString();
  153. }
  154. //
  155. // const bool as<bool>() const
  156. template <typename T>
  157. const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
  158. T>::type
  159. as() const {
  160. return asInteger() != 0;
  161. }
  162. //
  163. // JsonArray& as<JsonArray> const;
  164. // JsonArray& as<JsonArray&> const;
  165. template <typename T>
  166. typename TypeTraits::EnableIf<
  167. TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
  168. JsonArray>::value,
  169. JsonArray &>::type
  170. as() const {
  171. return asArray();
  172. }
  173. //
  174. // const JsonArray& as<const JsonArray&> const;
  175. template <typename T>
  176. typename TypeTraits::EnableIf<
  177. TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
  178. const JsonArray>::value,
  179. const JsonArray &>::type
  180. as() const {
  181. return asArray();
  182. }
  183. //
  184. // JsonObject& as<JsonObject> const;
  185. // JsonObject& as<JsonObject&> const;
  186. template <typename T>
  187. typename TypeTraits::EnableIf<
  188. TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
  189. JsonObject>::value,
  190. JsonObject &>::type
  191. as() const {
  192. return asObject();
  193. }
  194. //
  195. // JsonObject& as<const JsonObject> const;
  196. // JsonObject& as<const JsonObject&> const;
  197. template <typename T>
  198. typename TypeTraits::EnableIf<
  199. TypeTraits::IsSame<typename TypeTraits::RemoveReference<T>::type,
  200. const JsonObject>::value,
  201. const JsonObject &>::type
  202. as() const {
  203. return asObject();
  204. }
  205. // Tells weither the variant has the specified type.
  206. // Returns true if the variant has type type T, false otherwise.
  207. //
  208. // short as<short>() const;
  209. // int as<int>() const;
  210. // long as<long>() const;
  211. template <typename T>
  212. const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value,
  213. bool>::type
  214. is() const {
  215. return isInteger();
  216. }
  217. //
  218. // double is<double>() const;
  219. // float is<float>() const;
  220. template <typename T>
  221. const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
  222. bool>::type
  223. is() const {
  224. return isFloat();
  225. }
  226. //
  227. // const bool is<bool>() const
  228. template <typename T>
  229. const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
  230. bool>::type
  231. is() const {
  232. return isBoolean();
  233. }
  234. //
  235. // bool is<const char*>() const;
  236. // bool is<char*>() const;
  237. template <typename T>
  238. typename TypeTraits::EnableIf<TypeTraits::IsSame<T, const char *>::value ||
  239. TypeTraits::IsSame<T, char *>::value,
  240. bool>::type
  241. is() const {
  242. return isString();
  243. }
  244. //
  245. // bool is<JsonArray> const;
  246. // bool is<JsonArray&> const;
  247. // bool is<const JsonArray&> const;
  248. template <typename T>
  249. typename TypeTraits::EnableIf<
  250. TypeTraits::IsSame<
  251. typename TypeTraits::RemoveConst<
  252. typename TypeTraits::RemoveReference<T>::type>::type,
  253. JsonArray>::value,
  254. bool>::type
  255. is() const {
  256. return isArray();
  257. }
  258. //
  259. // JsonObject& as<JsonObject> const;
  260. // JsonObject& as<JsonObject&> const;
  261. // JsonObject& as<const JsonObject&> const;
  262. template <typename T>
  263. typename TypeTraits::EnableIf<
  264. TypeTraits::IsSame<
  265. typename TypeTraits::RemoveConst<
  266. typename TypeTraits::RemoveReference<T>::type>::type,
  267. JsonObject>::value,
  268. bool>::type
  269. is() const {
  270. return isObject();
  271. }
  272. // Returns true if the variant has a value
  273. bool success() const {
  274. return _type != Internals::JSON_UNDEFINED;
  275. }
  276. // Serialize the variant to a JsonWriter
  277. void writeTo(Internals::JsonWriter &writer) const;
  278. // Value returned if the variant has an incompatible type
  279. template <typename T>
  280. static typename Internals::JsonVariantAs<T>::type defaultValue() {
  281. return T();
  282. }
  283. const char *asString() const;
  284. JsonArray &asArray() const;
  285. JsonObject &asObject() const;
  286. private:
  287. // It's not allowed to store a char
  288. template <typename T>
  289. JsonVariant(T value, typename TypeTraits::EnableIf<
  290. TypeTraits::IsSame<T, char>::value>::type * = 0);
  291. String toString() const;
  292. Internals::JsonFloat asFloat() const;
  293. Internals::JsonInteger asInteger() const;
  294. Internals::JsonUInt asUnsignedInteger() const;
  295. bool isBoolean() const;
  296. bool isFloat() const;
  297. bool isInteger() const;
  298. bool isArray() const {
  299. return _type == Internals::JSON_ARRAY;
  300. }
  301. bool isObject() const {
  302. return _type == Internals::JSON_OBJECT;
  303. }
  304. bool isString() const {
  305. return _type == Internals::JSON_STRING;
  306. }
  307. // The current type of the variant
  308. Internals::JsonVariantType _type;
  309. // The various alternatives for the value of the variant.
  310. Internals::JsonVariantContent _content;
  311. };
  312. inline JsonVariant float_with_n_digits(float value, uint8_t digits) {
  313. return JsonVariant(value, digits);
  314. }
  315. inline JsonVariant double_with_n_digits(double value, uint8_t digits) {
  316. return JsonVariant(value, digits);
  317. }
  318. template <typename T>
  319. struct JsonVariant::IsConstructibleFrom {
  320. static const bool value =
  321. TypeTraits::IsIntegral<T>::value ||
  322. TypeTraits::IsFloatingPoint<T>::value ||
  323. TypeTraits::IsSame<T, bool>::value ||
  324. TypeTraits::IsSame<T, char *>::value ||
  325. TypeTraits::IsSame<T, const char *>::value ||
  326. TypeTraits::IsSame<T, RawJson>::value ||
  327. TypeTraits::IsSame<T, JsonArray &>::value ||
  328. TypeTraits::IsSame<T, const JsonArray &>::value ||
  329. TypeTraits::IsSame<T, JsonArraySubscript &>::value ||
  330. TypeTraits::IsSame<T, const JsonArraySubscript &>::value ||
  331. TypeTraits::IsSame<T, JsonObject &>::value ||
  332. TypeTraits::IsSame<T, const JsonObject &>::value ||
  333. TypeTraits::IsSame<T, JsonObjectSubscript<const char *> &>::value ||
  334. TypeTraits::IsSame<T, const JsonObjectSubscript<const char *> &>::value ||
  335. TypeTraits::IsSame<T, JsonObjectSubscript<String> &>::value ||
  336. TypeTraits::IsSame<T, const JsonObjectSubscript<String> &>::value ||
  337. TypeTraits::IsSame<T, JsonVariant &>::value ||
  338. TypeTraits::IsSame<T, const JsonVariant &>::value;
  339. };
  340. }