1 #include "../json/reflector.h"
2 #include "../json/serializable.h"
4 #include <c++utilities/conversion/stringbuilder.h>
5 #include <c++utilities/conversion/stringconversion.h>
6 #include <c++utilities/io/misc.h>
7 #include <c++utilities/tests/testutils.h>
9 using CppUtilities::operator<<;
10 #include <cppunit/TestFixture.h>
11 #include <cppunit/extensions/HelperMacros.h>
13 #include <rapidjson/document.h>
14 #include <rapidjson/stringbuffer.h>
15 #include <rapidjson/writer.h>
21 #include <unordered_map>
25 using namespace CPPUNIT_NS;
26 using namespace RAPIDJSON_NAMESPACE;
27 using namespace CppUtilities;
28 using namespace CppUtilities::Literals;
41 enum class SomeEnumClass {
53 map<string, int> someMap;
54 unordered_map<string, bool> someHash;
55 multimap<string, int> someMultimap;
56 unordered_multimap<string, int> someMultiHash;
58 multiset<string> someMultiset;
59 unordered_set<string> someUnorderedSet;
60 unordered_multiset<string> someUnorderedMultiset;
61 variant<monostate, string, int, float> someVariant;
62 variant<string, int, float> anotherVariant;
63 variant<string, int, float> yetAnotherVariant;
73 vector<TestObject> testObjects;
78 namespace JsonReflector {
80 template <>
inline void push<TestObject>(
const TestObject &reflectable, Value::Object &value, Document::AllocatorType &allocator)
82 push(reflectable.number,
"number", value, allocator);
83 push(reflectable.number2,
"number2", value, allocator);
84 push(reflectable.numbers,
"numbers", value, allocator);
85 push(reflectable.text,
"text", value, allocator);
86 push(reflectable.boolean,
"boolean", value, allocator);
87 push(reflectable.someMap,
"someMap", value, allocator);
88 push(reflectable.someHash,
"someHash", value, allocator);
89 push(reflectable.someMultimap,
"someMultimap", value, allocator);
90 push(reflectable.someMultiHash,
"someMultiHash", value, allocator);
91 push(reflectable.someSet,
"someSet", value, allocator);
92 push(reflectable.someMultiset,
"someMultiset", value, allocator);
93 push(reflectable.someUnorderedSet,
"someUnorderedSet", value, allocator);
94 push(reflectable.someUnorderedMultiset,
"someUnorderedMultiset", value, allocator);
95 push(reflectable.someVariant,
"someVariant", value, allocator);
96 push(reflectable.anotherVariant,
"anotherVariant", value, allocator);
97 push(reflectable.yetAnotherVariant,
"yetAnotherVariant", value, allocator);
100 template <>
inline void push<NestingObject>(
const NestingObject &reflectable, Value::Object &value, Document::AllocatorType &allocator)
102 push(reflectable.name,
"name", value, allocator);
103 push(reflectable.testObj,
"testObj", value, allocator);
106 template <>
inline void push<NestingArray>(
const NestingArray &reflectable, Value::Object &value, Document::AllocatorType &allocator)
108 push(reflectable.name,
"name", value, allocator);
109 push(reflectable.testObjects,
"testObjects", value, allocator);
113 inline void pull<TestObject>(TestObject &reflectable,
const GenericValue<UTF8<char>>::ConstObject &value,
JsonDeserializationErrors *errors)
115 const char *previousRecord;
120 pull(reflectable.number,
"number", value, errors);
121 pull(reflectable.number2,
"number2", value, errors);
122 pull(reflectable.numbers,
"numbers", value, errors);
123 pull(reflectable.text,
"text", value, errors);
124 pull(reflectable.boolean,
"boolean", value, errors);
125 pull(reflectable.someMap,
"someMap", value, errors);
126 pull(reflectable.someHash,
"someHash", value, errors);
127 pull(reflectable.someMultimap,
"someMultimap", value, errors);
128 pull(reflectable.someMultiHash,
"someMultiHash", value, errors);
129 pull(reflectable.someSet,
"someSet", value, errors);
130 pull(reflectable.someMultiset,
"someMultiset", value, errors);
131 pull(reflectable.someUnorderedSet,
"someUnorderedSet", value, errors);
132 pull(reflectable.someUnorderedMultiset,
"someUnorderedMultiset", value, errors);
133 pull(reflectable.someVariant,
"someVariant", value, errors);
134 pull(reflectable.anotherVariant,
"anotherVariant", value, errors);
135 pull(reflectable.yetAnotherVariant,
"yetAnotherVariant", value, errors);
142 inline void pull<NestingObject>(NestingObject &reflectable,
const GenericValue<UTF8<char>>::ConstObject &value,
JsonDeserializationErrors *errors)
144 const char *previousRecord;
149 pull(reflectable.name,
"name", value, errors);
150 pull(reflectable.testObj,
"testObj", value, errors);
157 inline void pull<NestingArray>(NestingArray &reflectable,
const GenericValue<UTF8<char>>::ConstObject &value,
JsonDeserializationErrors *errors)
159 const char *previousRecord;
164 pull(reflectable.name,
"name", value, errors);
165 pull(reflectable.testObjects,
"testObjects", value, errors);
184 CPPUNIT_TEST(testSerializePrimitives);
185 CPPUNIT_TEST(testSerializeSimpleObjects);
186 CPPUNIT_TEST(testSerializeNestedObjects);
187 CPPUNIT_TEST(testSerializeUniquePtr);
188 CPPUNIT_TEST(testSerializeSharedPtr);
189 CPPUNIT_TEST(testDeserializePrimitives);
190 CPPUNIT_TEST(testDeserializeSimpleObjects);
191 CPPUNIT_TEST(testDeserializeNestedObjects);
192 CPPUNIT_TEST(testDeserializeUniquePtr);
193 CPPUNIT_TEST(testDeserializeSharedPtr);
194 CPPUNIT_TEST(testHandlingParseError);
195 CPPUNIT_TEST(testHandlingTypeMismatch);
196 CPPUNIT_TEST_SUITE_END();
199 void setUp()
override;
200 void tearDown()
override;
203 void testSerializePrimitives();
204 void testSerializeSimpleObjects();
205 void testSerializeNestedObjects();
206 void testSerializeUniquePtr();
207 void testSerializeSharedPtr();
208 void testDeserializePrimitives();
209 void testDeserializeSimpleObjects();
210 void testDeserializeNestedObjects();
211 void testDeserializeUniquePtr();
212 void testDeserializeSharedPtr();
213 void testHandlingParseError();
214 void testHandlingTypeMismatch();
234 Document doc(kArrayType);
235 Document::AllocatorType &alloc = doc.GetAllocator();
237 Document::Array array(doc.GetArray());
240 const string foo(
"foo");
241 JsonReflector::push<string>(foo, array, alloc);
242 JsonReflector::push<const char *>(
"bar", array, alloc);
244 JsonReflector::push<int>(25, array, alloc);
245 JsonReflector::push<double>(12.5, array, alloc);
247 JsonReflector::push<SomeEnum>(SomeEnumItem2, array, alloc);
248 JsonReflector::push<SomeEnumClass>(SomeEnumClass::Item2, array, alloc);
249 JsonReflector::push<SomeEnumClass>(SomeEnumClass::Item3, array, alloc);
251 JsonReflector::push<vector<const char *>>({
"foo1",
"bar1" }, array, alloc);
252 JsonReflector::push<list<const char *>>({
"foo2",
"bar2" }, array, alloc);
253 JsonReflector::push<initializer_list<const char *>>({
"foo3",
"bar3" }, array, alloc);
254 JsonReflector::push<tuple<int, double>>(make_tuple(2, 413.0), array, alloc);
256 JsonReflector::push<bool>(
true, array, alloc);
257 JsonReflector::push<bool>(
false, array, alloc);
260 Writer<StringBuffer> jsonWriter(strbuf);
261 doc.Accept(jsonWriter);
262 CPPUNIT_ASSERT_EQUAL(
"[\"foo\",\"bar\",25,12.5,1,1,2,[\"foo1\",\"bar1\"],[\"foo2\",\"bar2\"],[\"foo3\",\"bar3\"],[2,413.0],true,false]"s,
263 string(strbuf.GetString()));
273 testObj.number2 = 3.141592653589793;
274 testObj.numbers = { 1, 2, 3, 4 };
275 testObj.text =
"test";
276 testObj.boolean =
false;
277 testObj.someMap = { {
"a", 1 }, {
"b", 2 } };
278 testObj.someHash = { {
"c",
true }, {
"d",
false } };
279 testObj.someMultimap = { {
"a", 1 }, {
"a", 2 }, {
"b", 3 } };
280 testObj.someMultiHash = { {
"a", 1 } };
281 testObj.someSet = {
"a",
"b",
"c" };
282 testObj.someMultiset = {
"a",
"b",
"b" };
283 testObj.someUnorderedSet = {
"a" };
284 testObj.someUnorderedMultiset = {
"b",
"b",
"b" };
285 testObj.someVariant = std::monostate{};
286 testObj.anotherVariant =
"foo";
287 testObj.yetAnotherVariant = 42;
288 CPPUNIT_ASSERT_EQUAL(
289 "{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{\"a\":1,\"b\":2},\"someHash\":{\"d\":false,\"c\":true},\"someMultimap\":{\"a\":[1,2],\"b\":[3]},\"someMultiHash\":{\"a\":[1]},\"someSet\":[\"a\",\"b\",\"c\"],\"someMultiset\":[\"a\",\"b\",\"b\"],\"someUnorderedSet\":[\"a\"],\"someUnorderedMultiset\":[\"b\",\"b\",\"b\"],\"someVariant\":{\"index\":0,\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"foo\"},\"yetAnotherVariant\":{\"index\":1,\"data\":42}}"s,
290 string(testObj.toJson().GetString()));
298 NestingObject nestingObj;
299 nestingObj.name =
"nesting";
300 TestObject &testObj = nestingObj.testObj;
302 testObj.number2 = 3.141592653589793;
303 testObj.numbers = { 1, 2, 3, 4 };
304 testObj.text =
"test";
305 testObj.boolean =
false;
306 CPPUNIT_ASSERT_EQUAL(
307 "{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{},\"someMultimap\":{},\"someMultiHash\":{},\"someSet\":[],\"someMultiset\":[],\"someUnorderedSet\":[],\"someUnorderedMultiset\":[],\"someVariant\":{\"index\":0,\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"\"},\"yetAnotherVariant\":{\"index\":0,\"data\":\"\"}}}"s,
308 string(nestingObj.toJson().GetString()));
310 NestingArray nestingArray;
311 nestingArray.name =
"nesting2";
312 nestingArray.testObjects.emplace_back(testObj);
313 nestingArray.testObjects.emplace_back(testObj);
314 nestingArray.testObjects.back().number = 43;
315 CPPUNIT_ASSERT_EQUAL(
316 "{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{},\"someMultimap\":{},\"someMultiHash\":{},\"someSet\":[],\"someMultiset\":[],\"someUnorderedSet\":[],\"someUnorderedMultiset\":[],\"someVariant\":{\"index\":0,\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"\"},\"yetAnotherVariant\":{\"index\":0,\"data\":\"\"}},{\"number\":43,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{},\"someMultimap\":{},\"someMultiHash\":{},\"someSet\":[],\"someMultiset\":[],\"someUnorderedSet\":[],\"someUnorderedMultiset\":[],\"someVariant\":{\"index\":0,\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"\"},\"yetAnotherVariant\":{\"index\":0,\"data\":\"\"}}]}"s,
317 string(nestingArray.toJson().GetString()));
319 vector<TestObject> nestedInVector;
320 nestedInVector.emplace_back(testObj);
321 CPPUNIT_ASSERT_EQUAL(
322 "[{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{},\"someMultimap\":{},\"someMultiHash\":{},\"someSet\":[],\"someMultiset\":[],\"someUnorderedSet\":[],\"someUnorderedMultiset\":[],\"someVariant\":{\"index\":0,\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"\"},\"yetAnotherVariant\":{\"index\":0,\"data\":\"\"}}]"s,
328 Document doc(kArrayType);
329 Document::AllocatorType &alloc = doc.GetAllocator();
331 Document::Array array(doc.GetArray());
333 const auto str = make_unique<string>(
"foo");
334 std::unique_ptr<string> nullStr;
335 const auto obj = make_unique<TestObject>();
337 obj->number2 = 3.141592653589793;
338 obj->numbers = { 1, 2, 3, 4 };
340 obj->boolean =
false;
347 Writer<StringBuffer> jsonWriter(strbuf);
348 doc.Accept(jsonWriter);
349 CPPUNIT_ASSERT_EQUAL(
350 "[\"foo\",null,{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"bar\",\"boolean\":false,\"someMap\":{},\"someHash\":{},\"someMultimap\":{},\"someMultiHash\":{},\"someSet\":[],\"someMultiset\":[],\"someUnorderedSet\":[],\"someUnorderedMultiset\":[],\"someVariant\":{\"index\":0,\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"\"},\"yetAnotherVariant\":{\"index\":0,\"data\":\"\"}}]"s,
351 string(strbuf.GetString()));
356 Document doc(kArrayType);
357 Document::AllocatorType &alloc = doc.GetAllocator();
359 Document::Array array(doc.GetArray());
361 const auto str = make_shared<string>(
"foo");
362 std::unique_ptr<string> nullStr;
363 const auto obj = make_shared<TestObject>();
365 obj->number2 = 3.141592653589793;
366 obj->numbers = { 1, 2, 3, 4 };
368 obj->boolean =
false;
375 Writer<StringBuffer> jsonWriter(strbuf);
376 doc.Accept(jsonWriter);
377 CPPUNIT_ASSERT_EQUAL(
378 "[\"foo\",null,{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"bar\",\"boolean\":false,\"someMap\":{},\"someHash\":{},\"someMultimap\":{},\"someMultiHash\":{},\"someSet\":[],\"someMultiset\":[],\"someUnorderedSet\":[],\"someUnorderedMultiset\":[],\"someVariant\":{\"index\":0,\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"\"},\"yetAnotherVariant\":{\"index\":0,\"data\":\"\"}}]"s,
379 string(strbuf.GetString()));
387 Document doc(kArrayType);
389 doc.Parse(
"[\"a\", 5, 5.0, 5e6, 4, \"test\", true, 4.125, false]");
390 auto array = doc.GetArray().begin();
393 int int1 = 0, int2 = 0;
394 bool bool1 =
false, bool2 =
true;
395 float float1 = 0.0f, float2 = 0.0f;
396 double double1 = 0.0;
408 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
409 CPPUNIT_ASSERT_EQUAL(
"a"s, str1);
410 CPPUNIT_ASSERT_EQUAL(5, int1);
411 CPPUNIT_ASSERT_EQUAL(5, int2);
412 CPPUNIT_ASSERT_EQUAL(5e6f, float1);
413 CPPUNIT_ASSERT_EQUAL(4.f, float2);
414 CPPUNIT_ASSERT_EQUAL(
"test"s, str2);
415 CPPUNIT_ASSERT_EQUAL(
true, bool1);
416 CPPUNIT_ASSERT_EQUAL(4.125, double1);
417 CPPUNIT_ASSERT_EQUAL(
false, bool2);
420 tuple<string, int, int, float, float, string, bool, double, bool> arrayAsTuple;
422 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
423 CPPUNIT_ASSERT_EQUAL(
"a"s, get<0>(arrayAsTuple));
424 CPPUNIT_ASSERT_EQUAL(5, get<1>(arrayAsTuple));
425 CPPUNIT_ASSERT_EQUAL(5, get<2>(arrayAsTuple));
426 CPPUNIT_ASSERT_EQUAL(5e6f, get<3>(arrayAsTuple));
427 CPPUNIT_ASSERT_EQUAL(4.f, get<4>(arrayAsTuple));
428 CPPUNIT_ASSERT_EQUAL(
"test"s, get<5>(arrayAsTuple));
429 CPPUNIT_ASSERT_EQUAL(
true, get<6>(arrayAsTuple));
430 CPPUNIT_ASSERT_EQUAL(4.125, get<7>(arrayAsTuple));
431 CPPUNIT_ASSERT_EQUAL(
false, get<8>(arrayAsTuple));
432 tuple<string, int> anotherTuple;
434 CPPUNIT_ASSERT_EQUAL(1_st, errors.size());
435 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::ArraySizeMismatch, errors.front().kind);
444 =
TestObject::fromJson(
"{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":"
445 "false,\"someMap\":{\"a\":1,\"b\":2},\"someHash\":{\"c\":true,\"d\":false},\"someMultimap\":{\"a\":[1,2],\"b\":[3]},"
446 "\"someMultiHash\":{\"a\":[4,5],\"b\":[6]},"
447 "\"someSet\":[\"a\",\"b\"],\"someMultiset\":["
448 "\"a\",\"a\"],\"someUnorderedSet\":[\"a\",\"b\"],\"someUnorderedMultiset\":[\"a\",\"a\"],\"someVariant\":{\"index\":0,"
449 "\"data\":null},\"anotherVariant\":{\"index\":0,\"data\":\"foo\"},\"yetAnotherVariant\":{\"index\":1,\"data\":42}}");
451 CPPUNIT_ASSERT_EQUAL(42, testObj.number);
452 CPPUNIT_ASSERT_EQUAL(3.141592653589793, testObj.number2);
453 CPPUNIT_ASSERT_EQUAL(vector<int>({ 1, 2, 3, 4 }), testObj.numbers);
454 CPPUNIT_ASSERT_EQUAL(
"test"s, testObj.text);
455 CPPUNIT_ASSERT_EQUAL(
false, testObj.boolean);
456 const map<string, int> expectedMap{ {
"a", 1 }, {
"b", 2 } };
457 CPPUNIT_ASSERT_EQUAL(expectedMap, testObj.someMap);
458 const unordered_map<string, bool> expectedHash{ {
"c",
true }, {
"d",
false } };
459 CPPUNIT_ASSERT_EQUAL(expectedHash, testObj.someHash);
460 const multimap<string, int> expectedMultiMap{ {
"a", 1 }, {
"a", 2 }, {
"b", 3 } };
461 CPPUNIT_ASSERT_EQUAL(expectedMultiMap, testObj.someMultimap);
462 const unordered_multimap<string, int> expectedUnorderedMultiMap{ {
"a", 4 }, {
"a", 5 }, {
"b", 6 } };
463 CPPUNIT_ASSERT_EQUAL(expectedUnorderedMultiMap, testObj.someMultiHash);
464 CPPUNIT_ASSERT_EQUAL(set<string>({
"a",
"b" }), testObj.someSet);
465 CPPUNIT_ASSERT_EQUAL(multiset<string>({
"a",
"a" }), testObj.someMultiset);
466 CPPUNIT_ASSERT_EQUAL(unordered_set<string>({
"a",
"b" }), testObj.someUnorderedSet);
467 CPPUNIT_ASSERT_EQUAL(unordered_multiset<string>({
"a",
"a" }), testObj.someUnorderedMultiset);
468 CPPUNIT_ASSERT_EQUAL(0_st, testObj.someVariant.index());
469 CPPUNIT_ASSERT_EQUAL(0_st, testObj.anotherVariant.index());
470 CPPUNIT_ASSERT_EQUAL(
"foo"s, std::get<0>(testObj.anotherVariant));
471 CPPUNIT_ASSERT_EQUAL(1_st, testObj.yetAnotherVariant.index());
472 CPPUNIT_ASSERT_EQUAL(42, std::get<1>(testObj.yetAnotherVariant));
481 const NestingObject nestingObj(
NestingObject::fromJson(
"{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,"
482 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}}",
484 const TestObject &testObj = nestingObj.testObj;
485 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
486 CPPUNIT_ASSERT_EQUAL(
"nesting"s, nestingObj.name);
487 CPPUNIT_ASSERT_EQUAL(42, testObj.number);
488 CPPUNIT_ASSERT_EQUAL(3.141592653589793, testObj.number2);
489 CPPUNIT_ASSERT_EQUAL(vector<int>({ 1, 2, 3, 4 }), testObj.numbers);
490 CPPUNIT_ASSERT_EQUAL(
"test"s, testObj.text);
491 CPPUNIT_ASSERT_EQUAL(
false, testObj.boolean);
493 const NestingArray nestingArray(
NestingArray::fromJson(
"{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,"
494 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},{\"number\":43,\"number2\":3."
495 "141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}]}",
497 const vector<TestObject> &testObjects = nestingArray.testObjects;
498 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
499 CPPUNIT_ASSERT_EQUAL(
"nesting2"s, nestingArray.name);
500 CPPUNIT_ASSERT_EQUAL(2_st, testObjects.size());
501 CPPUNIT_ASSERT_EQUAL(42, testObjects[0].number);
502 CPPUNIT_ASSERT_EQUAL(43, testObjects[1].number);
503 for (
const TestObject &testObj : testObjects) {
504 CPPUNIT_ASSERT_EQUAL(3.141592653589793, testObj.number2);
505 CPPUNIT_ASSERT_EQUAL(vector<int>({ 1, 2, 3, 4 }), testObj.numbers);
506 CPPUNIT_ASSERT_EQUAL(
"test"s, testObj.text);
507 CPPUNIT_ASSERT_EQUAL(
false, testObj.boolean);
511 "[{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false,\"someMap\":{},\"someHash\":{}}]",
513 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
514 CPPUNIT_ASSERT_EQUAL(1_st, nestedInVector.size());
515 CPPUNIT_ASSERT_EQUAL(42, nestedInVector[0].number);
516 CPPUNIT_ASSERT_EQUAL(4_st, nestedInVector[0].numbers.size());
517 CPPUNIT_ASSERT_EQUAL(
"test"s, nestedInVector[0].text);
522 Document doc(kArrayType);
523 doc.Parse(
"[\"foo\",null,{\"text\":\"bar\"}]");
524 auto array = doc.GetArray().begin();
526 unique_ptr<string> str;
527 unique_ptr<string> nullStr;
528 unique_ptr<TestObject> obj;
534 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
536 CPPUNIT_ASSERT_EQUAL(
"foo"s, *str);
537 CPPUNIT_ASSERT(!nullStr);
539 CPPUNIT_ASSERT_EQUAL(
"bar"s, obj->text);
544 Document doc(kArrayType);
545 doc.Parse(
"[\"foo\",null,{\"text\":\"bar\"}]");
546 auto array = doc.GetArray().begin();
548 shared_ptr<string> str;
549 shared_ptr<string> nullStr;
550 shared_ptr<TestObject> obj;
556 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
558 CPPUNIT_ASSERT_EQUAL(
"foo"s, *str);
559 CPPUNIT_ASSERT(!nullStr);
561 CPPUNIT_ASSERT_EQUAL(
"bar"s, obj->text);
570 NestingObject::fromJson(
"{\"name\":nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":"
571 "\"test\",\"boolean\":false}}");
572 CPPUNIT_FAIL(
"expected ParseResult thrown");
573 }
catch (
const RAPIDJSON_NAMESPACE::ParseResult &res) {
574 CPPUNIT_ASSERT_EQUAL(RAPIDJSON_NAMESPACE::kParseErrorValueInvalid, res.Code());
575 CPPUNIT_ASSERT_EQUAL(9_st, res.Offset());
585 NestingArray::fromJson(
"{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,"
586 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},{\"number\":43,\"number2\":3."
587 "141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}]}",
589 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
591 NestingObject::fromJson(
"{\"name\":\"nesting\",\"testObj\":{\"number\":\"42\",\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":"
592 "\"test\",\"boolean\":false,\"someSet\":[\"a\",\"a\"],\"someMultiset\":[\"a\",\"a\"],\"someUnorderedSet\":[\"a\",\"a\"],"
593 "\"someUnorderedMultiset\":[\"a\",\"a\"]}}",
595 CPPUNIT_ASSERT_EQUAL(3_st, errors.size());
596 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind);
597 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().expectedType);
598 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().actualType);
599 CPPUNIT_ASSERT_EQUAL(
"number"s,
string(errors.front().member));
600 CPPUNIT_ASSERT_EQUAL(
"TestObject"s,
string(errors.front().record));
601 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::UnexpectedDuplicate, errors[1].kind);
602 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors[1].expectedType);
603 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors[1].actualType);
604 CPPUNIT_ASSERT_EQUAL(
"someSet"s,
string(errors[1].member));
605 CPPUNIT_ASSERT_EQUAL(
"TestObject"s,
string(errors[1].record));
606 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::UnexpectedDuplicate, errors[2].kind);
607 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors[2].expectedType);
608 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors[2].actualType);
609 CPPUNIT_ASSERT_EQUAL(
"someUnorderedSet"s,
string(errors[2].member));
610 CPPUNIT_ASSERT_EQUAL(
"TestObject"s,
string(errors[2].record));
613 NestingObject::fromJson(
"{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,\"numbers\":1,\"text\":"
614 "\"test\",\"boolean\":false}}",
616 CPPUNIT_ASSERT_EQUAL(1_st, errors.size());
617 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind);
618 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().expectedType);
619 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().actualType);
620 CPPUNIT_ASSERT_EQUAL(
"numbers"s,
string(errors.front().member));
621 CPPUNIT_ASSERT_EQUAL(
"TestObject"s,
string(errors.front().record));
625 CPPUNIT_ASSERT_EQUAL(2_st, errors.size());
626 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind);
627 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().expectedType);
628 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().actualType);
629 CPPUNIT_ASSERT_EQUAL(
"name"s,
string(errors.front().member));
630 CPPUNIT_ASSERT_EQUAL(
"NestingObject"s,
string(errors.front().record));
631 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.back().kind);
632 CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors.back().expectedType);
633 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.back().actualType);
634 CPPUNIT_ASSERT_EQUAL(
"testObj"s,
string(errors.back().member));
635 CPPUNIT_ASSERT_EQUAL(
"NestingObject"s,
string(errors.back().record));
638 const NestingArray nestingArray(
639 NestingArray::fromJson(
"{\"name\":\"nesting2\",\"testObjects\":[25,{\"number\":42,\"number2\":3.141592653589793,"
640 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},\"foo\",{\"number\":43,\"number2\":3."
641 "141592653589793,\"numbers\":[1,2,3,4,\"bar\"],\"text\":\"test\",\"boolean\":false}]}",
643 CPPUNIT_ASSERT_EQUAL(3_st, errors.size());
644 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[0].kind);
645 CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[0].expectedType);
646 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[0].actualType);
647 CPPUNIT_ASSERT_EQUAL(
"testObjects"s,
string(errors[0].member));
648 CPPUNIT_ASSERT_EQUAL(
"NestingArray"s,
string(errors[0].record));
649 CPPUNIT_ASSERT_EQUAL(0_st, errors[0].index);
650 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[1].kind);
651 CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[1].expectedType);
652 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[1].actualType);
653 CPPUNIT_ASSERT_EQUAL(2_st, errors[1].index);
654 CPPUNIT_ASSERT_EQUAL(
"testObjects"s,
string(errors[1].member));
655 CPPUNIT_ASSERT_EQUAL(
"NestingArray"s,
string(errors[1].record));
656 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[2].kind);
657 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[2].expectedType);
658 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[2].actualType);
659 CPPUNIT_ASSERT_EQUAL(
"numbers"s,
string(errors[2].member));
660 CPPUNIT_ASSERT_EQUAL(
"TestObject"s,
string(errors[2].record));
661 CPPUNIT_ASSERT_EQUAL(4_st, errors[2].index);
664 errors.
throwOn = JsonDeserializationErrors::ThrowOn::TypeMismatch;