26struct TypeWithExternalUnifiedSerialisation
31 std::map<std::string, int> d;
33 auto operator== (
const TypeWithExternalUnifiedSerialisation& other)
const
35 const auto tie = [] (
const auto& x) {
return std::tie (x.a, x.b, x.c, x.d); };
36 return tie (*
this) == tie (other);
39 auto operator!= (
const TypeWithExternalUnifiedSerialisation& other)
const {
return ! operator== (other); }
45 static constexpr auto marshallingVersion = 2;
47 template <
typename Archive,
typename T>
48 static void serialise (Archive& archive, T& t)
50 archive (named (
"a", t.a),
58static_assert (detail::serialisationKind<TypeWithExternalUnifiedSerialisation> == detail::SerialisationKind::external);
60struct TypeWithInternalUnifiedSerialisation
67 auto operator== (
const TypeWithInternalUnifiedSerialisation& other)
const
69 const auto tie = [] (
const auto& x) {
return std::tie (x.a, x.b, x.c, x.d); };
70 return tie (*
this) == tie (other);
73 auto operator!= (
const TypeWithInternalUnifiedSerialisation& other)
const {
return ! operator== (other); }
75 static constexpr auto marshallingVersion = 5;
77 template <
typename Archive,
typename T>
78 static void serialise (Archive& archive, T& t)
80 archive (named (
"a", t.a),
87static_assert (detail::serialisationKind<TypeWithInternalUnifiedSerialisation> == detail::SerialisationKind::internal);
89struct TypeWithExternalSplitSerialisation
91 std::optional<String> a;
94 auto operator== (
const TypeWithExternalSplitSerialisation& other)
const
96 const auto tie = [] (
const auto& x) {
return std::tie (x.a, x.b); };
97 return tie (*
this) == tie (other);
100 auto operator!= (
const TypeWithExternalSplitSerialisation& other)
const {
return ! operator== (other); }
106 static constexpr auto marshallingVersion = 10;
108 template <
typename Archive>
109 static void load (Archive& archive, TypeWithExternalSplitSerialisation& t)
111 std::optional<String> a;
112 Array<String> hexStrings;
113 archive (named (
"a", a), named (
"b", hexStrings));
117 for (
auto& i : hexStrings)
118 b.add (i.getHexValue32());
123 template <
typename Archive>
124 static void save (Archive& archive,
const TypeWithExternalSplitSerialisation& t)
126 Array<String> hexStrings;
131 archive (named (
"a", t.a), named (
"b", hexStrings));
136static_assert (detail::serialisationKind<TypeWithExternalSplitSerialisation> == detail::SerialisationKind::external);
139static_assert (detail::serialisationKind<bool> == detail::SerialisationKind::primitive);
140static_assert (detail::serialisationKind< int8_t> == detail::SerialisationKind::primitive);
141static_assert (detail::serialisationKind< uint8_t> == detail::SerialisationKind::primitive);
142static_assert (detail::serialisationKind< int16_t> == detail::SerialisationKind::primitive);
143static_assert (detail::serialisationKind<uint16_t> == detail::SerialisationKind::primitive);
144static_assert (detail::serialisationKind< int32_t> == detail::SerialisationKind::primitive);
145static_assert (detail::serialisationKind<uint32_t> == detail::SerialisationKind::primitive);
146static_assert (detail::serialisationKind< int64_t> == detail::SerialisationKind::primitive);
147static_assert (detail::serialisationKind<uint64_t> == detail::SerialisationKind::primitive);
148static_assert (detail::serialisationKind<float> == detail::SerialisationKind::primitive);
149static_assert (detail::serialisationKind<double> == detail::SerialisationKind::primitive);
150static_assert (detail::serialisationKind<std::byte> == detail::SerialisationKind::primitive);
151static_assert (detail::serialisationKind<String> == detail::SerialisationKind::primitive);
154static_assert (detail::serialisationKind<Logger> == detail::SerialisationKind::none);
155static_assert (detail::serialisationKind<CriticalSection> == detail::SerialisationKind::none);
157struct TypeWithInternalSplitSerialisation
162 auto operator== (
const TypeWithInternalSplitSerialisation& other)
const
164 const auto tie = [] (
const auto& x) {
return std::tie (x.a, x.b); };
165 return tie (*
this) == tie (other);
168 auto operator!= (
const TypeWithInternalSplitSerialisation& other)
const {
return ! operator== (other); }
170 static constexpr auto marshallingVersion = 1;
172 template <
typename Archive>
173 static void load (Archive& archive, TypeWithInternalSplitSerialisation& t)
176 Array<String> hexStrings;
177 archive (named (
"a", a), named (
"b", hexStrings));
181 for (
auto& i : hexStrings)
182 b.add (i.getHexValue32());
187 template <
typename Archive>
188 static void save (Archive& archive,
const TypeWithInternalSplitSerialisation& t)
190 Array<String> hexStrings;
195 archive (named (
"a", t.a), named (
"b", hexStrings));
199static_assert (detail::serialisationKind<TypeWithInternalSplitSerialisation> == detail::SerialisationKind::internal);
201struct TypeWithBrokenObjectSerialisation
206 static constexpr auto marshallingVersion = std::nullopt;
208 template <
typename Archive,
typename T>
209 static void serialise (Archive& archive, T& t)
212 archive (named (
"a", t.a));
218struct TypeWithBrokenPrimitiveSerialisation
223 static constexpr auto marshallingVersion = std::nullopt;
225 template <
typename Archive,
typename T>
226 static void serialise (Archive& archive, T& t)
231 archive (named (
"b", t.b));
235struct TypeWithBrokenArraySerialisation
237 static constexpr auto marshallingVersion = std::nullopt;
239 template <
typename Archive,
typename T>
240 static void serialise (Archive& archive, T&)
246 archive (serialisationSize (size));
250struct TypeWithBrokenNestedSerialisation
253 TypeWithBrokenObjectSerialisation b;
255 static constexpr auto marshallingVersion = std::nullopt;
257 template <
typename Archive,
typename T>
258 static void serialise (Archive& archive, T& t)
260 archive (named (
"a", t.a), named (
"b", t.b));
264struct TypeWithBrokenDynamicSerialisation
266 std::vector<TypeWithBrokenObjectSerialisation> a;
268 static constexpr auto marshallingVersion = std::nullopt;
270 template <
typename Archive,
typename T>
271 static void serialise (Archive& archive, T& t)
277struct TypeWithVersionedSerialisation
279 int a{}, b{}, c{}, d{};
281 bool operator== (
const TypeWithVersionedSerialisation& other)
const
283 const auto tie = [] (
const auto& x) {
return std::tie (x.a, x.b, x.c, x.d); };
284 return tie (*
this) == tie (other);
287 bool operator!= (
const TypeWithVersionedSerialisation& other)
const {
return ! operator== (other); }
289 static constexpr auto marshallingVersion = 3;
291 template <
typename Archive,
typename T>
292 static void serialise (Archive& archive, T& t)
294 archive (named (
"a", t.a));
296 if (archive.getVersion() >= 1)
297 archive (named (
"b", t.b));
299 if (archive.getVersion() >= 2)
300 archive (named (
"c", t.c));
302 if (archive.getVersion() >= 3)
303 archive (named (
"d", t.d));
307struct TypeWithRawVarLast
313 bool operator== (
const TypeWithRawVarLast& other)
const
315 const auto tie = [] (
const auto& x) {
return std::tie (x.status, x.message, x.extended); };
316 return tie (*
this) == tie (other);
319 bool operator!= (
const TypeWithRawVarLast& other)
const {
return ! operator== (other); }
321 static constexpr auto marshallingVersion = std::nullopt;
323 template <
typename Archive,
typename T>
324 static void serialise (Archive& archive, T& t)
326 archive (named (
"status", t.status),
327 named (
"message", t.message),
328 named (
"extended", t.extended));
332struct TypeWithRawVarFirst
338 bool operator== (
const TypeWithRawVarFirst& other)
const
340 const auto tie = [] (
const auto& x) {
return std::tie (x.status, x.message, x.extended); };
341 return tie (*
this) == tie (other);
344 bool operator!= (
const TypeWithRawVarFirst& other)
const {
return ! operator== (other); }
346 static constexpr auto marshallingVersion = std::nullopt;
348 template <
typename Archive,
typename T>
349 static void serialise (Archive& archive, T& t)
351 archive (named (
"extended", t.extended),
352 named (
"status", t.status),
353 named (
"message", t.message));
357struct TypeWithInnerVar
362 bool operator== (
const TypeWithInnerVar& other)
const
364 const auto tie = [] (
const auto& x) {
return std::tie (x.eventId, x.payload); };
365 return tie (*
this) == tie (other);
368 bool operator!= (
const TypeWithInnerVar& other)
const {
return ! operator== (other); }
370 static constexpr auto marshallingVersion = std::nullopt;
372 template <
typename Archive,
typename T>
373 static void serialise (Archive& archive, T& t)
375 archive (named (
"eventId", t.eventId),
376 named (
"payload", t.payload));
380class JSONSerialisationTest final :
public UnitTest
383 JSONSerialisationTest() :
UnitTest (
"JSONSerialisation", UnitTestCategories::json) {}
395 expectDeepEqual (
ToVar::convert (String (
"hello world")),
"hello world");
396 expectDeepEqual (
ToVar::convert (std::vector<int> { 1, 2, 3 }), Array<var> { 1, 2, 3 });
397 expectDeepEqual (
ToVar::convert (TypeWithExternalUnifiedSerialisation { 7,
400 { {
"foo", 4 }, {
"bar", 5 } } }),
403 {
"b",
"hello world" },
404 {
"c", Array<var> { 5, 6, 7 } },
409 {
"second", 4 } }) } } }));
410 expectDeepEqual (
ToVar::convert (TypeWithInternalUnifiedSerialisation { 7.89,
413 {
"foo",
"bar",
"baz" } }),
417 {
"c",
"custom string" },
418 {
"d", Array<var> {
"foo",
"bar",
"baz" } } }));
419 expectDeepEqual (
ToVar::convert (TypeWithExternalSplitSerialisation {
"string", { 1, 2, 3 } }),
422 {
"b", Array<var> {
"0x1",
"0x2",
"0x3" } } }));
423 expectDeepEqual (
ToVar::convert (TypeWithInternalSplitSerialisation {
"string", { 16, 32, 48 } }),
426 {
"b", Array<var> {
"0x10",
"0x20",
"0x30" } } }));
432 expect (
ToVar::convert (TypeWithBrokenDynamicSerialisation { std::vector<TypeWithBrokenObjectSerialisation> (10) }) == std::nullopt);
434 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }),
440 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }, ToVar::Options {}.withVersionIncluded (
false)),
446 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }, ToVar::Options {}.withExplicitVersion (4)),
448 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }, ToVar::Options {}.withExplicitVersion (3)),
454 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }, ToVar::Options {}.withExplicitVersion (2)),
459 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }, ToVar::Options {}.withExplicitVersion (1)),
463 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }, ToVar::Options {}.withExplicitVersion (0)),
466 expectDeepEqual (
ToVar::convert (TypeWithVersionedSerialisation { 1, 2, 3, 4 }, ToVar::Options {}.withExplicitVersion (std::nullopt)),
469 expectDeepEqual (
ToVar::convert (TypeWithRawVarLast { 200,
"success",
true }),
474 {
"message",
"failure" },
475 {
"extended",
true } }) }),
477 {
"message",
"success" },
479 {
"message",
"failure" },
480 {
"extended",
true } }) } }));
482 expectDeepEqual (
ToVar::convert (TypeWithRawVarFirst { 200,
"success",
true }),
487 {
"message",
"failure" },
488 {
"extended",
true } }) }),
490 {
"message",
"success" },
492 {
"message",
"failure" },
493 {
"extended",
true } }) } }));
496 expectDeepEqual (
ToVar::convert (TypeWithInnerVar { 404, payload }),
513 {
"b",
"hello world" },
514 {
"c", Array<var> { 5, 6, 7 } },
519 {
"second", 4 } }) } } }))
520 == TypeWithExternalUnifiedSerialisation { 7,
523 { {
"foo", 4 }, {
"bar", 5 } } });
528 {
"c",
"custom string" },
529 {
"d", Array<var> {
"foo",
"bar",
"baz" } } }))
530 == TypeWithInternalUnifiedSerialisation { 7.89,
533 {
"foo",
"bar",
"baz" } });
537 {
"b", Array<var> {
"0x1",
"0x2",
"0x3" } } }))
538 == TypeWithExternalSplitSerialisation {
"string", { 1, 2, 3 } });
541 {
"b", Array<var> {
"0x10",
"0x20",
"0x30" } } }))
542 == TypeWithInternalSplitSerialisation {
"string", { 16, 32, 48 } });
559 == TypeWithVersionedSerialisation { 1, 2, 3, 4 });
565 == TypeWithVersionedSerialisation { 1, 2, 3, 4 });
570 == TypeWithVersionedSerialisation { 1, 2, 3, 0 });
574 == TypeWithVersionedSerialisation { 1, 2, 0, 0 });
577 == TypeWithVersionedSerialisation { 1, 0, 0, 0 });
579 == TypeWithVersionedSerialisation { 1, 0, 0, 0 });
581 const auto raw =
JSONUtils::makeObject ({ {
"status", 200 }, {
"message",
"success" }, {
"extended",
"another string" } });
586 var (Array<var> { 1, 2 }),
589 for (
const auto& payload : payloads)
591 const auto objectWithPayload =
JSONUtils::makeObject ({ {
"eventId", 404 }, {
"payload", payload } });
598 void expectDeepEqual (
const std::optional<var>& a,
const std::optional<var>& b)
600 const auto text = a.has_value() && b.has_value()
603 expect (deepEqual (a, b), text);
606 static bool deepEqual (
const std::optional<var>& a,
const std::optional<var>& b)
608 if (a.has_value() && b.has_value())
615static JSONSerialisationTest jsonSerialisationTest;
static std::optional< T > convert(const var &v)
static var fromString(StringRef)
static String toString(const var &objectToFormat, bool allOnOneLine=false, int maximumDecimalPlaces=15)
static String toHexString(IntegerType number)
static std::optional< var > convert(const T &t, const Options &options={})
UnitTest(const String &name, const String &category=String())
void beginTest(const String &testName)
void expect(bool testResult, const String &failureMessage=String())
static bool deepEqual(const var &a, const var &b)
static var makeObject(const std::map< Identifier, var > &source)