Added support for custom writer classes (closes #1088)

This commit is contained in:
Benoit Blanchon
2019-09-13 14:06:41 +02:00
parent 2078871f36
commit 498a2e4c1e
9 changed files with 133 additions and 30 deletions

View File

@ -1,6 +1,11 @@
ArduinoJson: change log
=======================
HEAD
----
* Added support for custom writer classes (issue #1088)
v6.12.0 (2019-09-05)
-------

View File

@ -3,6 +3,7 @@
# MIT License
add_executable(JsonSerializerTests
CustomWriter.cpp
JsonArray.cpp
JsonArrayPretty.cpp
JsonObject.cpp

View File

@ -0,0 +1,41 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#include <ArduinoJson.h>
#include <catch.hpp>
struct CustomWriter {
std::string str;
size_t write(uint8_t c) {
str.append(1, static_cast<char>(c));
return 1;
}
size_t write(const uint8_t *s, size_t n) {
str.append(reinterpret_cast<const char *>(s), n);
return n;
}
};
TEST_CASE("CustomWriter") {
DynamicJsonDocument doc(4096);
JsonArray array = doc.to<JsonArray>();
array.add(4);
array.add(2);
SECTION("serializeJson()") {
CustomWriter writer;
serializeJson(array, writer);
REQUIRE("[4,2]" == writer.str);
}
SECTION("serializeJsonPretty") {
CustomWriter writer;
serializeJsonPretty(array, writer);
REQUIRE("[\r\n 4,\r\n 2\r\n]" == writer.str);
}
}

View File

@ -2,10 +2,10 @@
# Copyright Benoit Blanchon 2014-2019
# MIT License
add_executable(JsonWriterTests
add_executable(TextFormatterTests
writeFloat.cpp
writeString.cpp
)
target_link_libraries(JsonWriterTests catch)
add_test(TextFormatter JsonWriterTests)
target_link_libraries(TextFormatterTests catch)
add_test(TextFormatter TextFormatterTests)

View File

@ -4,7 +4,9 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Serialization/WriterSelector.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <WString.h>
@ -79,4 +81,11 @@ class DynamicStringWriter<std::basic_string<char, TCharTraits, TAllocator> > {
string_type *_str;
};
#endif
template <typename TDestination>
struct WriterSelector<
TDestination,
typename enable_if<IsWriteableString<TDestination>::value>::type> {
typedef DynamicStringWriter<TDestination> writer_type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,37 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Serialization/WriterSelector.hpp>
namespace ARDUINOJSON_NAMESPACE {
class PrintWriter {
public:
explicit PrintWriter(Print& print) : _print(print) {}
size_t write(uint8_t c) {
return _print.write(c);
}
size_t write(const uint8_t* s, size_t n) {
return _print.write(s, n);
}
private:
// cannot be assigned
PrintWriter& operator=(const PrintWriter&);
Print& _print;
};
template <typename TDestination>
struct WriterSelector<
TDestination,
typename enable_if<is_base_of<Print, TDestination>::value>::type> {
typedef PrintWriter writer_type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -5,8 +5,7 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ArduinoJson/Serialization/WriterSelector.hpp>
#include <ostream>
@ -33,6 +32,11 @@ class StreamWriter {
std::ostream& _os;
};
} // namespace ARDUINOJSON_NAMESPACE
#endif // ARDUINOJSON_ENABLE_STD_STREAM
template <typename TDestination>
struct WriterSelector<
TDestination,
typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
typedef StreamWriter writer_type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,17 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TDestination, typename Enable = void>
struct WriterSelector {
// by default, assume destination implements the Writer concept
typedef TDestination& writer_type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -4,6 +4,7 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Serialization/DynamicStringWriter.hpp>
#include <ArduinoJson/Serialization/StaticStringWriter.hpp>
@ -11,30 +12,26 @@
#include <ArduinoJson/Serialization/StreamWriter.hpp>
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
#include <ArduinoJson/Serialization/PrintWriter.hpp>
#endif
namespace ARDUINOJSON_NAMESPACE {
template <template <typename> class TSerializer, typename TSource,
typename TDestination>
size_t doSerialize(const TSource &source, TDestination &destination) {
TSerializer<TDestination> serializer(destination);
typename TWriter>
size_t doSerialize(const TSource &source, TWriter &writer) {
TSerializer<TWriter> serializer(writer);
source.accept(serializer);
return serializer.bytesWritten();
}
#if ARDUINOJSON_ENABLE_STD_STREAM
template <template <typename> class TSerializer, typename TSource>
size_t serialize(const TSource &source, std::ostream &destination) {
StreamWriter writer(destination);
template <template <typename> class TSerializer, typename TSource,
typename TDestination>
size_t serialize(const TSource &source, TDestination &destination) {
typename WriterSelector<TDestination>::writer_type writer(destination);
return doSerialize<TSerializer>(source, writer);
}
#endif
#if ARDUINOJSON_ENABLE_ARDUINO_PRINT
template <template <typename> class TSerializer, typename TSource>
size_t serialize(const TSource &source, Print &destination) {
return doSerialize<TSerializer>(source, destination);
}
#endif
template <template <typename> class TSerializer, typename TSource>
size_t serialize(const TSource &source, char *buffer, size_t bufferSize) {
@ -48,12 +45,4 @@ size_t serialize(const TSource &source, char (&buffer)[N]) {
return doSerialize<TSerializer>(source, writer);
}
template <template <typename> class TSerializer, typename TSource,
typename TString>
typename enable_if<IsWriteableString<TString>::value, size_t>::type serialize(
const TSource &source, TString &str) {
DynamicStringWriter<TString> writer(str);
return doSerialize<TSerializer>(source, writer);
}
} // namespace ARDUINOJSON_NAMESPACE