ArduinoJson.h
Go to the documentation of this file.
1 /****
2  * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3  * Created 2015 by Skurydin Alexey
4  * http://github.com/SmingHub/Sming
5  * All files of the Sming Core are provided under the LGPL v3 license.
6  *
7  * ArduinoJson.h - JSON/MesagePack support for Sming using ArduinoJson V6
8  *
9  * @author mikee47 <mike@sillyhouse.net> May 2019
10  *
11  * Provides ArduinoJson customisations to help simplify usage with Sming.
12  *
13  * - Add support for FlashString in keys and values
14  * - Define enumeration for supported serialization formats (JSON/MessagePack)
15  * - Serialization/de-serialization functions with additional FlashString and stream pointer support:
16  * size_t Json::measure(source, format)
17  * size_t Json::serialize(source, destination, format)
18  * bool Json::deserialize(doc, input, format)
19  * bool Json::deserialize(doc, input, size, format)
20  * bool Json::loadFromFile(doc, filename, format)
21  * bool Json::saveToFile(doc, filename, format)
22  * - Support functions to simplify usage
23  * bool Json::getValue(source&, dest&)
24  *
25  * ArduinoJson V6 vs V5
26  * --------------------
27  *
28  * See the migration guide for details: https://arduinojson.org/v6/doc/upgrade
29  *
30  * Caution! If accessing a a key which doesn't exist:
31  * `json["key"].as<String>()` will return "null" (the serialised value)
32  * `json["key"].as<const char*>()` will return nullptr (same as ArduinoJson V5 `asString()` method)
33  *
34  ****/
35 
36 #pragma once
37 
38 #include "../ArduinoJson/src/ArduinoJson.h"
40 #include "FlashStringReader.hpp"
41 #include <Data/Stream/FileStream.h>
42 #include <Data/CString.h>
43 
44 #ifndef JSON_ENABLE_COMPACT
45 #define JSON_ENABLE_COMPACT 1
46 #endif
47 #ifndef JSON_ENABLE_PRETTY
48 #define JSON_ENABLE_PRETTY 1
49 #endif
50 #ifndef JSON_ENABLE_MSGPACK
51 #define JSON_ENABLE_MSGPACK 1
52 #endif
53 #ifndef JSON_FORMAT_DEFAULT
54 #define JSON_FORMAT_DEFAULT Json::Compact
55 #endif
56 
57 namespace Json
58 {
80 template <typename TSource, typename TDest> bool getValue(const TSource& source, TDest& dest)
81 {
82  if(source.isNull()) {
83  return false;
84  } else {
85  dest = source.template as<TDest>();
86  return true;
87  }
88 }
89 
96 template <typename TSource, typename TDest> bool getValueChanged(const TSource& source, TDest& dest)
97 {
98  if(source.isNull()) {
99  return false;
100  }
101 
102  TDest value = source.template as<TDest>();
103  if(value == dest) {
104  return false; // value unchanged
105  }
106 
107  dest = value;
108  return true;
109 }
110 
118 };
119 
121 {
122  fmt = SerializationFormat(int(fmt) + 1);
123  return fmt;
124 }
125 
132 template <typename TSource> size_t measure(const TSource& source, SerializationFormat format = JSON_FORMAT_DEFAULT)
133 {
134  switch(format) {
135 #if JSON_ENABLE_COMPACT
136  case Compact:
137  return measureJson(source);
138 #endif
139 #if JSON_ENABLE_PRETTY
140  case Pretty:
141  return measureJsonPretty(source);
142 #endif
143 #if JSON_ENABLE_MSGPACK
144  case MessagePack:
145  return measureMsgPack(source);
146 #endif
147  default:
148  return 0;
149  }
150 }
151 
159 template <typename TSource, typename TDestination>
160 size_t serialize(const TSource& source, TDestination& destination, SerializationFormat format = JSON_FORMAT_DEFAULT)
161 {
162  switch(format) {
163 #if JSON_ENABLE_COMPACT
164  case Compact:
165  return serializeJson(source, destination);
166 #endif
167 #if JSON_ENABLE_PRETTY
168  case Pretty:
169  return serializeJsonPretty(source, destination);
170 #endif
171 #if JSON_ENABLE_MSGPACK
172  case MessagePack:
173  return serializeMsgPack(source, destination);
174 #endif
175  default:
176  return 0;
177  }
178 }
179 
188 template <typename TSource, typename TPrint>
189 typename std::enable_if<std::is_base_of<Print, TPrint>::value, size_t>::type
190 serialize(const TSource& source, TPrint* destination, SerializationFormat format = JSON_FORMAT_DEFAULT)
191 {
192  return (destination == nullptr) ? 0 : serialize(source, *destination, format);
193 }
194 
203 template <typename TSource>
204 size_t serialize(const TSource& source, char* buffer, size_t bufferSize,
206 {
207  switch(format) {
208 #if JSON_ENABLE_COMPACT
209  case Compact:
210  return serializeJson(source, buffer, bufferSize);
211 #endif
212 #if JSON_ENABLE_PRETTY
213  case Pretty:
214  return serializeJsonPretty(source, buffer, bufferSize);
215 #endif
216 #if JSON_ENABLE_MSGPACK
217  case MessagePack:
218  return serializeMsgPack(source, buffer, bufferSize);
219 #endif
220  default:
221  return 0;
222  }
223 }
224 
225 template <typename TSource>
226 size_t serialize(const TSource& source, CString& output, SerializationFormat format = JSON_FORMAT_DEFAULT)
227 {
228  auto measuredSize = Json::measure(source, format);
229  output.reset(new char[measuredSize + 1]);
230  size_t actualSize = Json::serialize(source, output.get(), measuredSize + 1, format);
231  assert(actualSize <= measuredSize);
232  output.get()[actualSize] = '\0';
233  return actualSize;
234 }
235 
242 template <typename TSource> String serialize(const TSource& source, SerializationFormat format = JSON_FORMAT_DEFAULT)
243 {
244  String result;
245  serialize(source, result, format);
246  return result;
247 }
248 
256 template <typename TSource>
257 bool saveToFile(const TSource& source, const String& filename, SerializationFormat format = JSON_FORMAT_DEFAULT)
258 {
260  if(!stream.isValid()) {
261  return false;
262  }
263 
264  if(serialize(source, stream, format) == 0) {
265  return false;
266  }
267 
268  return stream.getLastError() == 0;
269 }
270 
271 template <typename TInput>
272 bool deserializeInternal(JsonDocument& doc, TInput& input, SerializationFormat format = JSON_FORMAT_DEFAULT)
273 {
274  switch(format) {
275 #if JSON_ENABLE_COMPACT || JSON_ENABLE_PRETTY
276  case Compact:
277  case Pretty:
278  return deserializeJson(doc, input) == DeserializationError::Ok;
279 #endif
280 #if JSON_ENABLE_MSGPACK
281  case MessagePack:
282  return deserializeMsgPack(doc, input) == DeserializationError::Ok;
283 #endif
284  default:
285  return false;
286  }
287 }
288 
308 template <typename TInput>
309 bool deserialize(JsonDocument& doc, TInput& input, SerializationFormat format = JSON_FORMAT_DEFAULT)
310 {
311  return deserializeInternal(doc, input, format);
312 }
313 
330 template <typename TInput>
331 typename std::enable_if<!std::is_base_of<Stream, TInput>::value, bool>::type
332 deserialize(JsonDocument& doc, TInput* input, SerializationFormat format = JSON_FORMAT_DEFAULT)
333 {
334  return deserializeInternal(doc, input, format);
335 }
336 
346 template <typename TStream>
347 typename std::enable_if<std::is_base_of<Stream, TStream>::value, bool>::type
348 deserialize(JsonDocument& doc, TStream* input, SerializationFormat format = JSON_FORMAT_DEFAULT)
349 {
350  return (input == nullptr) ? false : deserializeInternal(doc, *input, format);
351 }
352 
369 template <typename TInput>
370 bool deserialize(JsonDocument& doc, TInput* input, size_t inputSize, SerializationFormat format = JSON_FORMAT_DEFAULT)
371 {
372  switch(format) {
373 #if JSON_ENABLE_COMPACT || JSON_ENABLE_PRETTY
374  case Compact:
375  case Pretty:
376  return deserializeJson(doc, input, inputSize) == DeserializationError::Ok;
377 #endif
378 #if JSON_ENABLE_MSGPACK
379  case MessagePack:
380  return deserializeMsgPack(doc, input, inputSize) == DeserializationError::Ok;
381 #endif
382  default:
383  return false;
384  }
385 }
386 
387 template <> inline bool deserialize(JsonDocument& doc, CString& input, SerializationFormat format)
388 {
389  return Json::deserialize(doc, input.c_str(), input.length(), format);
390 }
391 
399 inline bool loadFromFile(JsonDocument& doc, const String& filename, SerializationFormat format = JSON_FORMAT_DEFAULT)
400 {
401  FileStream stream(filename);
402  return stream.isValid() ? deserialize(doc, stream, format) : false;
403 }
404 
405 } // namespace Json
const char * c_str() const
Definition: CString.h:104
@ Pretty
Prettified JSON format, with spaces and line breaks.
Definition: ArduinoJson.h:116
bool deserializeInternal(JsonDocument &doc, TInput &input, SerializationFormat format=JSON_FORMAT_DEFAULT)
Definition: ArduinoJson.h:272
The String class.
Definition: WString.h:136
SerializationFormat operator++(SerializationFormat &fmt)
Definition: ArduinoJson.h:120
@ Compact
Compact JSON format.
Definition: ArduinoJson.h:115
File stream class.
Definition: FileStream.h:20
bool getValue(const TSource &source, TDest &dest)
Copies a Json data value to a variable, but only if it exists.
Definition: ArduinoJson.h:80
static constexpr OpenFlags WriteOnly
Write-only.
Definition: File.h:73
int getLastError()
determine if an error occurred during operation
Definition: FsBase.h:66
Class to manage a NUL-terminated C-style string When storing persistent strings in RAM the regular St...
Definition: CString.h:26
Definition: ArduinoJson.h:57
bool saveToFile(const TSource &source, const String &filename, SerializationFormat format=JSON_FORMAT_DEFAULT)
Save a Json object to a file in a specified format.
Definition: ArduinoJson.h:257
@ MessagePack
Message Pack (compact binary) format.
Definition: ArduinoJson.h:117
size_t measure(const TSource &source, SerializationFormat format=JSON_FORMAT_DEFAULT)
Compute the size of a serialized Json object for a specified format.
Definition: ArduinoJson.h:132
#define JSON_FORMAT_DEFAULT
Definition: ArduinoJson.h:54
bool getValueChanged(const TSource &source, TDest &dest)
Copies a Json data value to a variable, but only if it exists and its value has changed.
Definition: ArduinoJson.h:96
SerializationFormat
Describes format of serialized Json object.
Definition: ArduinoJson.h:114
bool isValid() const override
Determine if the stream object contains valid data.
Definition: IFS/FileStream.h:113
size_t serialize(const TSource &source, TDestination &destination, SerializationFormat format=JSON_FORMAT_DEFAULT)
Write a Json object in a specified format.
Definition: ArduinoJson.h:160
bool deserialize(JsonDocument &doc, TInput &input, SerializationFormat format=JSON_FORMAT_DEFAULT)
Read a JsonDocument from formatted data.
Definition: ArduinoJson.h:309
bool loadFromFile(JsonDocument &doc, const String &filename, SerializationFormat format=JSON_FORMAT_DEFAULT)
Parses the contents of a serialized file into a JsonDocument object.
Definition: ArduinoJson.h:399
size_t length() const
Definition: CString.h:160
static constexpr OpenFlags CreateNewAlways
Create new file or overwrite file if it exists.
Definition: File.h:78