7 #ifndef CPPWAMP_INTERNAL_JSONENCODING_HPP
8 #define CPPWAMP_INTERNAL_JSONENCODING_HPP
10 #include <jsoncons/json_encoder.hpp>
11 #include "../blob.hpp"
12 #include "../null.hpp"
13 #include "../variantdefs.hpp"
23 template <
typename TEncoder>
24 class JsonVariantEncodingVisitor
27 using Sink =
typename TEncoder::sink_type;
30 explicit JsonVariantEncodingVisitor(Sink sink, TEncoder& encoder)
39 encoder_.null_value();
43 void operator()(
Bool b)
45 encoder_.bool_value(b);
49 void operator()(
Int n)
51 encoder_.int64_value(n);
55 void operator()(
UInt n)
57 encoder_.uint64_value(n);
61 void operator()(
Real x)
63 encoder_.double_value(x);
67 void operator()(
const String& s)
69 encoder_.string_value({s.data(), s.size()});
73 void operator()(
const Blob& b)
75 static constexpr
char prefix[] =
"\"\\u0000";
76 if (context_.back().needsArraySeparator())
78 auto data =
reinterpret_cast<const typename Sink::value_type*
>(prefix);
79 sink_.append(data,
sizeof(prefix) - 1);
81 sink_.push_back(
'\"');
85 template <
typename TVariant>
86 void operator()(
const std::vector<TVariant>& array)
89 encoder_.begin_array(
array.size());
90 for (
const auto& v: array)
91 wamp::apply(*
this, v);
97 template <
typename TVariant>
98 void operator()(
const std::map<String, TVariant>&
object)
101 encoder_.begin_object(
object.size());
102 for (
const auto& kv:
object)
104 const auto& key = kv.first;
105 encoder_.key({key.data(), key.size()});
106 wamp::apply(*
this, kv.second);
108 encoder_.end_object();
116 Context(
bool isArray =
false) : isArray(isArray), isPopulated(false) {}
118 bool needsArraySeparator()
const {
return isArray && isPopulated;}
120 void populate() {isPopulated =
true;}
123 bool isPopulated : 1;
126 void next() {context_.back().populate();}
128 void enter(
bool isArray =
false) {context_.push_back(isArray);}
132 assert(!context_.empty());
138 std::vector<Context> context_;
142 template <
typename TSink>
146 using value_type = char;
148 JsonSinkProxy() =
default;
150 JsonSinkProxy(TSink& out) : sink_(&out) {}
152 void append(
const value_type* data,
size_t size)
154 auto ptr =
reinterpret_cast<const SinkByte*
>(data);
155 sink_->append(ptr, size);
158 void push_back(value_type
byte)
162 std::memcpy(&value, &
byte,
sizeof(
byte));
163 sink_->push_back(value);
169 using SinkByte =
typename TSink::value_type;
171 TSink* sink_ =
nullptr;
178 template <
typename TSink>
179 class JsonEncoderImpl
182 JsonEncoderImpl() : encoder_(Proxy{}) {}
184 template <
typename TVariant,
typename TOutput>
185 void encode(
const TVariant& variant, TOutput& output)
192 encoder_.reset(std::move(proxy));
193 internal::JsonVariantEncodingVisitor<Encoder> visitor(proxy, encoder_);
194 wamp::apply(visitor, variant);
198 using Proxy = internal::JsonSinkProxy<TSink>;
199 using Encoder = jsoncons::basic_compact_json_encoder<char, Proxy>;
207 #endif // CPPWAMP_INTERNAL_JSONENCODING_HPP