diff --git a/src/ArduinoJson/JsonVariant.hpp b/src/ArduinoJson/JsonVariant.hpp index 598df822..1a79af06 100644 --- a/src/ArduinoJson/JsonVariant.hpp +++ b/src/ArduinoJson/JsonVariant.hpp @@ -27,10 +27,6 @@ namespace ArduinoJson { // Forward declarations. class JsonArray; class JsonObject; -namespace Internals { -template -class JsonSerializer; -} // A variant that can be a any value serializable to a JSON value. // @@ -40,9 +36,6 @@ class JsonSerializer; // - a string (const char*) // - a reference to a JsonArray or JsonObject class JsonVariant : public Internals::JsonVariantBase { - template - friend class Internals::JsonSerializer; - public: // Creates an uninitialized JsonVariant JsonVariant() : _type(Internals::JSON_UNDEFINED) {} @@ -317,6 +310,39 @@ class JsonVariant : public Internals::JsonVariantBase { return _type != Internals::JSON_UNDEFINED; } + template + void visit(Visitor visitor) const { + using namespace Internals; + switch (_type) { + case JSON_FLOAT: + return visitor.acceptFloat(_content.asFloat); + + case JSON_ARRAY: + return visitor.acceptArray(*_content.asArray); + + case JSON_OBJECT: + return visitor.acceptObject(*_content.asObject); + + case JSON_STRING: + return visitor.acceptString(_content.asString); + + case JSON_UNPARSED: + return visitor.acceptRawJson(_content.asString); + + case JSON_NEGATIVE_INTEGER: + return visitor.acceptNegativeInteger(_content.asInteger); + + case JSON_POSITIVE_INTEGER: + return visitor.acceptPositiveInteger(_content.asInteger); + + case JSON_BOOLEAN: + return visitor.acceptBoolean(_content.asInteger != 0); + + default: // JSON_UNDEFINED + return visitor.acceptUndefined(); + } + } + private: JsonArray &variantAsArray() const; JsonObject &variantAsObject() const; diff --git a/src/ArduinoJson/Serialization/JsonSerializer.hpp b/src/ArduinoJson/Serialization/JsonSerializer.hpp index 211e9fbf..1bf8810d 100644 --- a/src/ArduinoJson/Serialization/JsonSerializer.hpp +++ b/src/ArduinoJson/Serialization/JsonSerializer.hpp @@ -36,6 +36,47 @@ class JsonSerializer { template static void serialize(const JsonObjectSubscript &, Writer &); static void serialize(const JsonVariant &, Writer &); + + struct Visitor { + Visitor(Writer *writer) : _writer(writer) {} + + void acceptFloat(JsonFloat value) { + _writer->writeFloat(value); + } + + void acceptArray(const JsonArray &value) { + serialize(value, *_writer); + } + + void acceptObject(const JsonObject &value) { + serialize(value, *_writer); + } + + void acceptString(const char *value) { + _writer->writeString(value); + } + + void acceptRawJson(const char *value) { + _writer->writeRaw(value); + } + + void acceptNegativeInteger(JsonUInt value) { + _writer->writeRaw('-'); + _writer->writeInteger(value); + } + + void acceptPositiveInteger(JsonUInt value) { + _writer->writeInteger(value); + } + + void acceptBoolean(bool value) { + _writer->writeBoolean(value); + } + + void acceptUndefined() {} + + Writer *_writer; + }; }; } // namespace Internals diff --git a/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp b/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp index 0faae276..da24cd93 100644 --- a/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp +++ b/src/ArduinoJson/Serialization/JsonSerializerImpl.hpp @@ -65,39 +65,5 @@ inline void ArduinoJson::Internals::JsonSerializer::serialize( template inline void ArduinoJson::Internals::JsonSerializer::serialize( const JsonVariant& variant, Writer& writer) { - switch (variant._type) { - case JSON_FLOAT: - writer.writeFloat(variant._content.asFloat); - return; - - case JSON_ARRAY: - serialize(*variant._content.asArray, writer); - return; - - case JSON_OBJECT: - serialize(*variant._content.asObject, writer); - return; - - case JSON_STRING: - writer.writeString(variant._content.asString); - return; - - case JSON_UNPARSED: - writer.writeRaw(variant._content.asString); - return; - - case JSON_NEGATIVE_INTEGER: - writer.writeRaw('-'); // Falls through. - - case JSON_POSITIVE_INTEGER: - writer.writeInteger(variant._content.asInteger); - return; - - case JSON_BOOLEAN: - writer.writeBoolean(variant._content.asInteger != 0); - return; - - default: // JSON_UNDEFINED - return; - } + variant.visit(Visitor(&writer)); }