forked from bblanchon/ArduinoJson
Reduced the size of the pretty JSON serializer
This commit is contained in:
@ -20,6 +20,8 @@ HEAD
|
|||||||
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
|
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
|
||||||
* Added `JsonDocument::isNull()`
|
* Added `JsonDocument::isNull()`
|
||||||
* Added `JsonDocument::operator[]`
|
* Added `JsonDocument::operator[]`
|
||||||
|
* Added `ARDUINOJSON_TAB` to configure the indentation character
|
||||||
|
* Reduced the size of the pretty JSON serializer
|
||||||
|
|
||||||
> ### BREAKING CHANGES
|
> ### BREAKING CHANGES
|
||||||
>
|
>
|
||||||
|
@ -39,13 +39,13 @@ void setup() {
|
|||||||
data.add(48.756080);
|
data.add(48.756080);
|
||||||
data.add(2.302038);
|
data.add(2.302038);
|
||||||
|
|
||||||
serializeJson(root, Serial);
|
serializeJson(doc, Serial);
|
||||||
// This prints:
|
// This prints:
|
||||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
|
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
serializeJsonPretty(root, Serial);
|
serializeJsonPretty(doc, Serial);
|
||||||
// This prints:
|
// This prints:
|
||||||
// {
|
// {
|
||||||
// "sensor": "gps",
|
// "sensor": "gps",
|
||||||
|
@ -79,7 +79,7 @@ void loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Serial.print(F("Sending: "));
|
Serial.print(F("Sending: "));
|
||||||
serializeJson(root, Serial);
|
serializeJson(doc, Serial);
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
// Write response headers
|
// Write response headers
|
||||||
@ -89,7 +89,7 @@ void loop() {
|
|||||||
client.println();
|
client.println();
|
||||||
|
|
||||||
// Write JSON document
|
// Write JSON document
|
||||||
serializeJsonPretty(root, client);
|
serializeJsonPretty(doc, client);
|
||||||
|
|
||||||
// Disconnect
|
// Disconnect
|
||||||
client.stop();
|
client.stop();
|
||||||
|
@ -75,11 +75,11 @@ void loop() {
|
|||||||
Serial.print(remoteIp);
|
Serial.print(remoteIp);
|
||||||
Serial.print(F(" on port "));
|
Serial.print(F(" on port "));
|
||||||
Serial.println(remotePort);
|
Serial.println(remotePort);
|
||||||
serializeJson(root, Serial);
|
serializeJson(doc, Serial);
|
||||||
|
|
||||||
// Send UDP packet
|
// Send UDP packet
|
||||||
udp.beginPacket(remoteIp, remotePort);
|
udp.beginPacket(remoteIp, remotePort);
|
||||||
serializeJson(root, udp);
|
serializeJson(doc, udp);
|
||||||
udp.println();
|
udp.println();
|
||||||
udp.endPacket();
|
udp.endPacket();
|
||||||
|
|
||||||
|
@ -140,3 +140,7 @@
|
|||||||
#define ARDUINOJSON_LITTLE_ENDIAN 0
|
#define ARDUINOJSON_LITTLE_ENDIAN 0
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARDUINOJSON_TAB
|
||||||
|
#define ARDUINOJSON_TAB " "
|
||||||
|
#endif
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2018
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
// Decorator on top of Print to allow indented output.
|
|
||||||
// This class is used by serializeJsonPretty() but can also be used
|
|
||||||
// for your own purpose, like logging.
|
|
||||||
template <typename Print>
|
|
||||||
class IndentedPrint {
|
|
||||||
public:
|
|
||||||
explicit IndentedPrint(Print &p) : sink(&p) {
|
|
||||||
level = 0;
|
|
||||||
tabSize = 2;
|
|
||||||
isNewLine = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
|
||||||
size_t n = 0;
|
|
||||||
if (isNewLine) n += writeTabs();
|
|
||||||
n += sink->write(c);
|
|
||||||
isNewLine = c == '\n';
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const uint8_t *s, size_t n) {
|
|
||||||
// TODO: optimize
|
|
||||||
size_t bytesWritten = 0;
|
|
||||||
while (n > 0) {
|
|
||||||
bytesWritten += write(*s++);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
return bytesWritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adds one level of indentation
|
|
||||||
void indent() {
|
|
||||||
if (level < MAX_LEVEL) level++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Removes one level of indentation
|
|
||||||
void unindent() {
|
|
||||||
if (level > 0) level--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the number of space printed for each level of indentation
|
|
||||||
void setTabSize(uint8_t n) {
|
|
||||||
if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Print *sink;
|
|
||||||
uint8_t level : 4;
|
|
||||||
uint8_t tabSize : 3;
|
|
||||||
bool isNewLine : 1;
|
|
||||||
|
|
||||||
size_t writeTabs() {
|
|
||||||
size_t n = 0;
|
|
||||||
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const int MAX_LEVEL = 15; // because it's only 4 bits
|
|
||||||
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
|
|
||||||
};
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
@ -7,21 +7,17 @@
|
|||||||
#include "../Misc/Visitable.hpp"
|
#include "../Misc/Visitable.hpp"
|
||||||
#include "../Serialization/measure.hpp"
|
#include "../Serialization/measure.hpp"
|
||||||
#include "../Serialization/serialize.hpp"
|
#include "../Serialization/serialize.hpp"
|
||||||
#include "JsonWriter.hpp"
|
#include "TextFormatter.hpp"
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class JsonSerializer {
|
class JsonSerializer {
|
||||||
public:
|
public:
|
||||||
JsonSerializer(TWriter &writer) : _writer(writer) {}
|
JsonSerializer(TWriter &writer) : _formatter(writer) {}
|
||||||
|
|
||||||
void visitFloat(Float value) {
|
FORCE_INLINE void visitArray(const CollectionData &array) {
|
||||||
_writer.writeFloat(value);
|
write('[');
|
||||||
}
|
|
||||||
|
|
||||||
void visitArray(const CollectionData &array) {
|
|
||||||
_writer.beginArray();
|
|
||||||
|
|
||||||
VariantSlot *slot = array.head();
|
VariantSlot *slot = array.head();
|
||||||
|
|
||||||
@ -31,63 +27,74 @@ class JsonSerializer {
|
|||||||
slot = slot->next();
|
slot = slot->next();
|
||||||
if (slot == 0) break;
|
if (slot == 0) break;
|
||||||
|
|
||||||
_writer.writeComma();
|
write(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.endArray();
|
write(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitObject(const CollectionData &object) {
|
void visitObject(const CollectionData &object) {
|
||||||
_writer.beginObject();
|
write('{');
|
||||||
|
|
||||||
VariantSlot *slot = object.head();
|
VariantSlot *slot = object.head();
|
||||||
|
|
||||||
while (slot != 0) {
|
while (slot != 0) {
|
||||||
_writer.writeString(slot->key());
|
_formatter.writeString(slot->key());
|
||||||
_writer.writeColon();
|
write(':');
|
||||||
slot->data()->accept(*this);
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
slot = slot->next();
|
slot = slot->next();
|
||||||
if (slot == 0) break;
|
if (slot == 0) break;
|
||||||
|
|
||||||
_writer.writeComma();
|
write(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.endObject();
|
write('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitFloat(Float value) {
|
||||||
|
_formatter.writeFloat(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitString(const char *value) {
|
void visitString(const char *value) {
|
||||||
_writer.writeString(value);
|
_formatter.writeString(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitRawJson(const char *data, size_t n) {
|
void visitRawJson(const char *data, size_t n) {
|
||||||
// TODO
|
_formatter.writeRaw(data, n);
|
||||||
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNegativeInteger(UInt value) {
|
void visitNegativeInteger(UInt value) {
|
||||||
_writer.writeRaw('-');
|
_formatter.writeNegativeInteger(value);
|
||||||
_writer.writeInteger(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitPositiveInteger(UInt value) {
|
void visitPositiveInteger(UInt value) {
|
||||||
_writer.writeInteger(value);
|
_formatter.writePositiveInteger(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitBoolean(bool value) {
|
void visitBoolean(bool value) {
|
||||||
_writer.writeBoolean(value);
|
_formatter.writeBoolean(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visitNull() {
|
void visitNull() {
|
||||||
_writer.writeRaw("null");
|
_formatter.writeRaw("null");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bytesWritten() const {
|
size_t bytesWritten() const {
|
||||||
return _writer.bytesWritten();
|
return _formatter.bytesWritten();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void write(char c) {
|
||||||
|
_formatter.writeRaw(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(const char *s) {
|
||||||
|
_formatter.writeRaw(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonWriter<TWriter> _writer;
|
TextFormatter<TWriter> _formatter;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSource, typename TDestination>
|
template <typename TSource, typename TDestination>
|
||||||
|
@ -4,37 +4,68 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
#include "../Serialization/measure.hpp"
|
#include "../Serialization/measure.hpp"
|
||||||
#include "../Serialization/serialize.hpp"
|
#include "../Serialization/serialize.hpp"
|
||||||
#include "./IndentedPrint.hpp"
|
#include "JsonSerializer.hpp"
|
||||||
#include "./JsonSerializer.hpp"
|
|
||||||
#include "./Prettyfier.hpp"
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TPrint>
|
template <typename TWriter>
|
||||||
class PrettyJsonSerializer_Base {
|
class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||||
public:
|
typedef JsonSerializer<TWriter> base;
|
||||||
PrettyJsonSerializer_Base(TPrint &output)
|
|
||||||
: _indentedPrint(output), _prettyfier(_indentedPrint) {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
IndentedPrint<TPrint> _indentedPrint;
|
|
||||||
Prettyfier<TPrint> _prettyfier;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TPrint>
|
|
||||||
class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
|
|
||||||
public JsonSerializer<Prettyfier<TPrint> > {
|
|
||||||
public:
|
public:
|
||||||
PrettyJsonSerializer(TPrint &output)
|
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
|
||||||
: PrettyJsonSerializer_Base<TPrint>(output),
|
|
||||||
JsonSerializer<Prettyfier<TPrint> >(
|
void visitArray(const CollectionData &array) {
|
||||||
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
|
VariantSlot *slot = array.head();
|
||||||
|
if (!slot) return base::write("[]");
|
||||||
|
|
||||||
|
base::write("[\r\n");
|
||||||
|
_nesting++;
|
||||||
|
while (slot != 0) {
|
||||||
|
indent();
|
||||||
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
|
slot = slot->next();
|
||||||
|
base::write(slot ? ",\r\n" : "\r\n");
|
||||||
|
}
|
||||||
|
_nesting--;
|
||||||
|
indent();
|
||||||
|
base::write("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitObject(const CollectionData &object) {
|
||||||
|
VariantSlot *slot = object.head();
|
||||||
|
if (!slot) return base::write("{}");
|
||||||
|
|
||||||
|
base::write("{\r\n");
|
||||||
|
_nesting++;
|
||||||
|
while (slot != 0) {
|
||||||
|
indent();
|
||||||
|
base::visitString(slot->key());
|
||||||
|
base::write(": ");
|
||||||
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
|
slot = slot->next();
|
||||||
|
base::write(slot ? ",\r\n" : "\r\n");
|
||||||
|
}
|
||||||
|
_nesting--;
|
||||||
|
indent();
|
||||||
|
base::write("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void indent() {
|
||||||
|
for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t _nesting;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSource, typename TDestination>
|
template <typename TSource, typename TDestination>
|
||||||
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
|
size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
|
||||||
return serialize<PrettyJsonSerializer>(source, destination);
|
return serialize<PrettyJsonSerializer>(source, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,143 +0,0 @@
|
|||||||
// ArduinoJson - arduinojson.org
|
|
||||||
// Copyright Benoit Blanchon 2014-2018
|
|
||||||
// MIT License
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "IndentedPrint.hpp"
|
|
||||||
|
|
||||||
namespace ARDUINOJSON_NAMESPACE {
|
|
||||||
|
|
||||||
// Converts a compact JSON string into an indented one.
|
|
||||||
template <typename TWriter>
|
|
||||||
class Prettyfier {
|
|
||||||
public:
|
|
||||||
explicit Prettyfier(IndentedPrint<TWriter>& p) : _sink(p) {
|
|
||||||
_previousChar = 0;
|
|
||||||
_inString = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
|
||||||
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(char(c));
|
|
||||||
_previousChar = char(c);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(const uint8_t* s, size_t n) {
|
|
||||||
// TODO: optimize
|
|
||||||
size_t bytesWritten = 0;
|
|
||||||
while (n > 0) {
|
|
||||||
bytesWritten += write(*s++);
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
return bytesWritten;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
|
|
||||||
|
|
||||||
bool inEmptyBlock() {
|
|
||||||
return _previousChar == '{' || _previousChar == '[';
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t handleStringChar(uint8_t c) {
|
|
||||||
bool isQuote = c == '"' && _previousChar != '\\';
|
|
||||||
|
|
||||||
if (isQuote) _inString = false;
|
|
||||||
|
|
||||||
return _sink.write(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t handleMarkupChar(char c) {
|
|
||||||
switch (c) {
|
|
||||||
case '{':
|
|
||||||
case '[':
|
|
||||||
return writeBlockOpen(c);
|
|
||||||
|
|
||||||
case '}':
|
|
||||||
case ']':
|
|
||||||
return writeBlockClose(c);
|
|
||||||
|
|
||||||
case ':':
|
|
||||||
return writeColon();
|
|
||||||
|
|
||||||
case ',':
|
|
||||||
return writeComma();
|
|
||||||
|
|
||||||
case '"':
|
|
||||||
return writeQuoteOpen();
|
|
||||||
|
|
||||||
default:
|
|
||||||
return writeNormalChar(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t writeBlockClose(char c) {
|
|
||||||
size_t n = 0;
|
|
||||||
n += unindentIfNeeded();
|
|
||||||
n += write(c);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t writeBlockOpen(char c) {
|
|
||||||
size_t n = 0;
|
|
||||||
n += indentIfNeeded();
|
|
||||||
n += write(c);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t writeColon() {
|
|
||||||
size_t n = 0;
|
|
||||||
n += write(": ");
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t writeComma() {
|
|
||||||
size_t n = 0;
|
|
||||||
n += write(",\r\n");
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t writeQuoteOpen() {
|
|
||||||
_inString = true;
|
|
||||||
size_t n = 0;
|
|
||||||
n += indentIfNeeded();
|
|
||||||
n += write('"');
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t writeNormalChar(char c) {
|
|
||||||
size_t n = 0;
|
|
||||||
n += indentIfNeeded();
|
|
||||||
n += write(c);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t indentIfNeeded() {
|
|
||||||
if (!inEmptyBlock()) return 0;
|
|
||||||
|
|
||||||
_sink.indent();
|
|
||||||
return write("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t unindentIfNeeded() {
|
|
||||||
if (inEmptyBlock()) return 0;
|
|
||||||
|
|
||||||
_sink.unindent();
|
|
||||||
return write("\r\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t write(char c) {
|
|
||||||
return _sink.write(static_cast<uint8_t>(c));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
size_t write(const char (&s)[N]) {
|
|
||||||
return _sink.write(reinterpret_cast<const uint8_t*>(s), N - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
char _previousChar;
|
|
||||||
IndentedPrint<TWriter>& _sink;
|
|
||||||
bool _inString;
|
|
||||||
};
|
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
|
@ -14,36 +14,15 @@
|
|||||||
namespace ARDUINOJSON_NAMESPACE {
|
namespace ARDUINOJSON_NAMESPACE {
|
||||||
|
|
||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class JsonWriter {
|
class TextFormatter {
|
||||||
public:
|
public:
|
||||||
explicit JsonWriter(TWriter &writer) : _writer(writer), _length(0) {}
|
explicit TextFormatter(TWriter &writer) : _writer(writer), _length(0) {}
|
||||||
|
|
||||||
// Returns the number of bytes sent to the TWriter implementation.
|
// Returns the number of bytes sent to the TWriter implementation.
|
||||||
size_t bytesWritten() const {
|
size_t bytesWritten() const {
|
||||||
return _length;
|
return _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void beginArray() {
|
|
||||||
writeRaw('[');
|
|
||||||
}
|
|
||||||
void endArray() {
|
|
||||||
writeRaw(']');
|
|
||||||
}
|
|
||||||
|
|
||||||
void beginObject() {
|
|
||||||
writeRaw('{');
|
|
||||||
}
|
|
||||||
void endObject() {
|
|
||||||
writeRaw('}');
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeColon() {
|
|
||||||
writeRaw(':');
|
|
||||||
}
|
|
||||||
void writeComma() {
|
|
||||||
writeRaw(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeBoolean(bool value) {
|
void writeBoolean(bool value) {
|
||||||
if (value)
|
if (value)
|
||||||
writeRaw("true");
|
writeRaw("true");
|
||||||
@ -84,22 +63,27 @@ class JsonWriter {
|
|||||||
|
|
||||||
FloatParts<T> parts(value);
|
FloatParts<T> parts(value);
|
||||||
|
|
||||||
writeInteger(parts.integral);
|
writePositiveInteger(parts.integral);
|
||||||
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
|
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
|
||||||
|
|
||||||
if (parts.exponent < 0) {
|
if (parts.exponent < 0) {
|
||||||
writeRaw("e-");
|
writeRaw("e-");
|
||||||
writeInteger(-parts.exponent);
|
writePositiveInteger(-parts.exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parts.exponent > 0) {
|
if (parts.exponent > 0) {
|
||||||
writeRaw('e');
|
writeRaw('e');
|
||||||
writeInteger(parts.exponent);
|
writePositiveInteger(parts.exponent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeNegativeInteger(UInt value) {
|
||||||
|
writeRaw('-');
|
||||||
|
writePositiveInteger(value);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void writeInteger(T value) {
|
void writePositiveInteger(T value) {
|
||||||
char buffer[22];
|
char buffer[22];
|
||||||
char *end = buffer + sizeof(buffer);
|
char *end = buffer + sizeof(buffer);
|
||||||
char *begin = end;
|
char *begin = end;
|
||||||
@ -134,10 +118,16 @@ class JsonWriter {
|
|||||||
void writeRaw(const char *s) {
|
void writeRaw(const char *s) {
|
||||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
|
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeRaw(const char *s, size_t n) {
|
||||||
|
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), n);
|
||||||
|
}
|
||||||
|
|
||||||
void writeRaw(const char *begin, const char *end) {
|
void writeRaw(const char *begin, const char *end) {
|
||||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
|
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
|
||||||
static_cast<size_t>(end - begin));
|
static_cast<size_t>(end - begin));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void writeRaw(const char (&s)[N]) {
|
void writeRaw(const char (&s)[N]) {
|
||||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
|
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
|
||||||
@ -151,6 +141,6 @@ class JsonWriter {
|
|||||||
size_t _length;
|
size_t _length;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
|
||||||
};
|
};
|
||||||
} // namespace ARDUINOJSON_NAMESPACE
|
} // namespace ARDUINOJSON_NAMESPACE
|
@ -78,7 +78,7 @@ add_subdirectory(JsonDocument)
|
|||||||
add_subdirectory(JsonObject)
|
add_subdirectory(JsonObject)
|
||||||
add_subdirectory(JsonSerializer)
|
add_subdirectory(JsonSerializer)
|
||||||
add_subdirectory(JsonVariant)
|
add_subdirectory(JsonVariant)
|
||||||
add_subdirectory(JsonWriter)
|
add_subdirectory(TextFormatter)
|
||||||
add_subdirectory(MemoryPool)
|
add_subdirectory(MemoryPool)
|
||||||
add_subdirectory(Misc)
|
add_subdirectory(Misc)
|
||||||
add_subdirectory(MixedConfiguration)
|
add_subdirectory(MixedConfiguration)
|
||||||
|
@ -8,4 +8,4 @@ add_executable(JsonWriterTests
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(JsonWriterTests catch)
|
target_link_libraries(JsonWriterTests catch)
|
||||||
add_test(JsonWriter JsonWriterTests)
|
add_test(TextFormatter JsonWriterTests)
|
@ -6,7 +6,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <ArduinoJson/Json/JsonWriter.hpp>
|
#include <ArduinoJson/Json/TextFormatter.hpp>
|
||||||
#include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
|
#include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
|
||||||
|
|
||||||
using namespace ARDUINOJSON_NAMESPACE;
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
@ -15,13 +15,13 @@ template <typename TFloat>
|
|||||||
void check(TFloat input, const std::string& expected) {
|
void check(TFloat input, const std::string& expected) {
|
||||||
std::string output;
|
std::string output;
|
||||||
DynamicStringWriter<std::string> sb(output);
|
DynamicStringWriter<std::string> sb(output);
|
||||||
JsonWriter<DynamicStringWriter<std::string> > writer(sb);
|
TextFormatter<DynamicStringWriter<std::string> > writer(sb);
|
||||||
writer.writeFloat(input);
|
writer.writeFloat(input);
|
||||||
REQUIRE(writer.bytesWritten() == output.size());
|
REQUIRE(writer.bytesWritten() == output.size());
|
||||||
CHECK(expected == output);
|
CHECK(expected == output);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonWriter::writeFloat(double)") {
|
TEST_CASE("TextFormatter::writeFloat(double)") {
|
||||||
SECTION("Pi") {
|
SECTION("Pi") {
|
||||||
check<double>(3.14159265359, "3.141592654");
|
check<double>(3.14159265359, "3.141592654");
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ TEST_CASE("JsonWriter::writeFloat(double)") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonWriter::writeFloat(float)") {
|
TEST_CASE("TextFormatter::writeFloat(float)") {
|
||||||
SECTION("Pi") {
|
SECTION("Pi") {
|
||||||
check<float>(3.14159265359f, "3.141593");
|
check<float>(3.14159265359f, "3.141593");
|
||||||
}
|
}
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include <ArduinoJson/Json/JsonWriter.hpp>
|
#include <ArduinoJson/Json/TextFormatter.hpp>
|
||||||
#include <ArduinoJson/Serialization/StaticStringWriter.hpp>
|
#include <ArduinoJson/Serialization/StaticStringWriter.hpp>
|
||||||
|
|
||||||
using namespace ARDUINOJSON_NAMESPACE;
|
using namespace ARDUINOJSON_NAMESPACE;
|
||||||
@ -12,13 +12,13 @@ using namespace ARDUINOJSON_NAMESPACE;
|
|||||||
void check(const char* input, std::string expected) {
|
void check(const char* input, std::string expected) {
|
||||||
char output[1024];
|
char output[1024];
|
||||||
StaticStringWriter sb(output, sizeof(output));
|
StaticStringWriter sb(output, sizeof(output));
|
||||||
JsonWriter<StaticStringWriter> writer(sb);
|
TextFormatter<StaticStringWriter> writer(sb);
|
||||||
writer.writeString(input);
|
writer.writeString(input);
|
||||||
REQUIRE(expected == output);
|
REQUIRE(expected == output);
|
||||||
REQUIRE(writer.bytesWritten() == expected.size());
|
REQUIRE(writer.bytesWritten() == expected.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("JsonWriter::writeString()") {
|
TEST_CASE("TextFormatter::writeString()") {
|
||||||
SECTION("Null") {
|
SECTION("Null") {
|
||||||
check(0, "null");
|
check(0, "null");
|
||||||
}
|
}
|
Reference in New Issue
Block a user