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 
43 #ifndef JSON_ENABLE_COMPACT
44 #define JSON_ENABLE_COMPACT 1
45 #endif
46 #ifndef JSON_ENABLE_PRETTY
47 #define JSON_ENABLE_PRETTY 1
48 #endif
49 #ifndef JSON_ENABLE_MSGPACK
50 #define JSON_ENABLE_MSGPACK 1
51 #endif
52 #ifndef JSON_FORMAT_DEFAULT
53 #define JSON_FORMAT_DEFAULT Json::Compact
54 #endif
55 
56 namespace Json
57 {
79 template <typename TSource, typename TDest> bool getValue(const TSource& source, TDest& dest)
80 {
81  if(source.isNull()) {
82  return false;
83  } else {
84  dest = source.template as<TDest>();
85  return true;
86  }
87 }
88 
95 template <typename TSource, typename TDest> bool getValueChanged(const TSource& source, TDest& dest)
96 {
97  if(source.isNull()) {
98  return false;
99  }
100 
101  TDest value = source.template as<TDest>();
102  if(value == dest) {
103  return false; // value unchanged
104  }
105 
106  dest = value;
107  return true;
108 }
109 
117 };
118 
120 {
121  fmt = SerializationFormat(int(fmt) + 1);
122  return fmt;
123 }
124 
131 template <typename TSource> size_t measure(const TSource& source, SerializationFormat format = JSON_FORMAT_DEFAULT)
132 {
133  switch(format) {
134 #if JSON_ENABLE_COMPACT
135  case Compact:
136  return measureJson(source);
137 #endif
138 #if JSON_ENABLE_PRETTY
139  case Pretty:
140  return measureJsonPretty(source);
141 #endif
142 #if JSON_ENABLE_MSGPACK
143  case MessagePack:
144  return measureMsgPack(source);
145 #endif
146  default:
147  return 0;
148  }
149 }
150 
158 template <typename TSource, typename TDestination>
159 size_t serialize(const TSource& source, TDestination& destination, SerializationFormat format = JSON_FORMAT_DEFAULT)
160 {
161  switch(format) {
162 #if JSON_ENABLE_COMPACT
163  case Compact:
164  return serializeJson(source, destination);
165 #endif
166 #if JSON_ENABLE_PRETTY
167  case Pretty:
168  return serializeJsonPretty(source, destination);
169 #endif
170 #if JSON_ENABLE_MSGPACK
171  case MessagePack:
172  return serializeMsgPack(source, destination);
173 #endif
174  default:
175  return 0;
176  }
177 }
178 
187 template <typename TSource, typename TPrint>
188 typename std::enable_if<std::is_base_of<Print, TPrint>::value, size_t>::type
189 serialize(const TSource& source, TPrint* destination, SerializationFormat format = JSON_FORMAT_DEFAULT)
190 {
191  return (destination == nullptr) ? 0 : serialize(source, *destination, format);
192 }
193 
202 template <typename TSource>
203 size_t serialize(const TSource& source, char* buffer, size_t bufferSize,
205 {
206  switch(format) {
207 #if JSON_ENABLE_COMPACT
208  case Compact:
209  return serializeJson(source, buffer, bufferSize);
210 #endif
211 #if JSON_ENABLE_PRETTY
212  case Pretty:
213  return serializeJsonPretty(source, buffer, bufferSize);
214 #endif
215 #if JSON_ENABLE_MSGPACK
216  case MessagePack:
217  return serializeMsgPack(source, buffer, bufferSize);
218 #endif
219  default:
220  return 0;
221  }
222 }
223 
230 template <typename TSource> String serialize(const TSource& source, SerializationFormat format = JSON_FORMAT_DEFAULT)
231 {
232  String result;
233  serialize(source, result, format);
234  return result;
235 }
236 
244 template <typename TSource>
245 bool saveToFile(const TSource& source, const String& filename, SerializationFormat format = JSON_FORMAT_DEFAULT)
246 {
247  FileStream stream(filename, eFO_WriteOnly | eFO_CreateNewAlways);
248  if(!stream.isValid()) {
249  return false;
250  }
251 
252  if(serialize(source, stream, format) == 0) {
253  return false;
254  }
255 
256  return stream.getLastError() == 0;
257 }
258 
259 template <typename TInput>
260 bool deserializeInternal(JsonDocument& doc, TInput& input, SerializationFormat format = JSON_FORMAT_DEFAULT)
261 {
262  switch(format) {
263 #if JSON_ENABLE_COMPACT || JSON_ENABLE_PRETTY
264  case Compact:
265  case Pretty:
266  return deserializeJson(doc, input) == DeserializationError::Ok;
267 #endif
268 #if JSON_ENABLE_MSGPACK
269  case MessagePack:
270  return deserializeMsgPack(doc, input) == DeserializationError::Ok;
271 #endif
272  default:
273  return false;
274  }
275 }
276 
296 template <typename TInput>
297 bool deserialize(JsonDocument& doc, TInput& input, SerializationFormat format = JSON_FORMAT_DEFAULT)
298 {
299  return deserializeInternal(doc, input, format);
300 }
301 
318 template <typename TInput>
319 typename std::enable_if<!std::is_base_of<Stream, TInput>::value, bool>::type
320 deserialize(JsonDocument& doc, TInput* input, SerializationFormat format = JSON_FORMAT_DEFAULT)
321 {
322  return deserializeInternal(doc, input, format);
323 }
324 
334 template <typename TStream>
335 typename std::enable_if<std::is_base_of<Stream, TStream>::value, bool>::type
336 deserialize(JsonDocument& doc, TStream* input, SerializationFormat format = JSON_FORMAT_DEFAULT)
337 {
338  return (input == nullptr) ? false : deserializeInternal(doc, *input, format);
339 }
340 
357 template <typename TInput>
358 bool deserialize(JsonDocument& doc, TInput* input, size_t inputSize, SerializationFormat format = JSON_FORMAT_DEFAULT)
359 {
360  switch(format) {
361 #if JSON_ENABLE_COMPACT || JSON_ENABLE_PRETTY
362  case Compact:
363  case Pretty:
364  return deserializeJson(doc, input, inputSize) == DeserializationError::Ok;
365 #endif
366 #if JSON_ENABLE_MSGPACK
367  case MessagePack:
368  return deserializeMsgPack(doc, input, inputSize) == DeserializationError::Ok;
369 #endif
370  default:
371  return false;
372  }
373 }
374 
382 inline bool loadFromFile(JsonDocument& doc, const String& filename, SerializationFormat format = JSON_FORMAT_DEFAULT)
383 {
384  FileStream stream(filename);
385  return stream.isValid() ? deserialize(doc, stream, format) : false;
386 }
387 
388 } // namespace Json
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:95
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:382
#define JSON_FORMAT_DEFAULT
Definition: ArduinoJson.h:53
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:245
bool isValid() const override
Determine if the stream object contains valid data.
Definition: FileStream.h:102
int getLastError()
determine if an error occurred during operation
Definition: FileStream.h:136
The String class.
Definition: WString.h:136
bool getValue(const TSource &source, TDest &dest)
Copies a Json data value to a variable, but only if it exists.
Definition: ArduinoJson.h:79
File stream class.
Definition: FileStream.h:23
Prettified JSON format, with spaces and line breaks.
Definition: ArduinoJson.h:115
Message Pack (compact binary) format.
Definition: ArduinoJson.h:116
Definition: ArduinoJson.h:56
SerializationFormat
Describes format of serialized Json object.
Definition: ArduinoJson.h:113
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:131
Compact JSON format.
Definition: ArduinoJson.h:114
Create new file even if file exists.
Definition: FileSystem.h:32
bool deserialize(JsonDocument &doc, TInput &input, SerializationFormat format=JSON_FORMAT_DEFAULT)
Read a JsonDocument from formatted data.
Definition: ArduinoJson.h:297
SerializationFormat operator++(SerializationFormat &fmt)
Definition: ArduinoJson.h:119
Write only file.
Definition: FileSystem.h:27
size_t serialize(const TSource &source, TDestination &destination, SerializationFormat format=JSON_FORMAT_DEFAULT)
Write a Json object in a specified format.
Definition: ArduinoJson.h:159
bool deserializeInternal(JsonDocument &doc, TInput &input, SerializationFormat format=JSON_FORMAT_DEFAULT)
Definition: ArduinoJson.h:260