Reflection for RapidJSON 0.0.16
Reflection for serializing/deserializing with RapidJSON
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
jsonreflector-boosthana.cpp
Go to the documentation of this file.
3
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>
8
9using CppUtilities::operator<<; // must be visible prior to the call site
10#include <cppunit/TestFixture.h>
11#include <cppunit/extensions/HelperMacros.h>
12
13#include <rapidjson/document.h>
14#include <rapidjson/stringbuffer.h>
15#include <rapidjson/writer.h>
16
17#include <iostream>
18#include <string>
19#include <vector>
20
21using namespace std;
22using namespace CPPUNIT_NS;
23using namespace RAPIDJSON_NAMESPACE;
24using namespace CppUtilities;
25using namespace CppUtilities::Literals;
26using namespace ReflectiveRapidJSON;
27
29
30// define some structs for testing serialization
31struct TestObjectHana : public JsonSerializable<TestObjectHana> {
32 BOOST_HANA_DEFINE_STRUCT(TestObjectHana, (int, number), (double, number2), (vector<int>, numbers), (string, text), (bool, boolean));
33};
34
35struct NestingObjectHana : public JsonSerializable<NestingObjectHana> {
36 BOOST_HANA_DEFINE_STRUCT(NestingObjectHana, (string, name), (TestObjectHana, testObj));
37};
38
39struct NestingArrayHana : public JsonSerializable<NestingArrayHana> {
40 BOOST_HANA_DEFINE_STRUCT(NestingArrayHana, (string, name), (vector<TestObjectHana>, testObjects));
41};
42
44
49class JsonReflectorBoostHanaTests : public TestFixture {
50 CPPUNIT_TEST_SUITE(JsonReflectorBoostHanaTests);
51 CPPUNIT_TEST(testSerializeSimpleObjects);
52 CPPUNIT_TEST(testSerializeNestedObjects);
53 CPPUNIT_TEST(testDeserializeSimpleObjects);
54 CPPUNIT_TEST(testDeserializeNestedObjects);
55 CPPUNIT_TEST(testHandlingTypeMismatch);
56 CPPUNIT_TEST_SUITE_END();
57
58public:
59 void setUp() override;
60 void tearDown() override;
61
69
70private:
71};
72
74
78
82
87{
88 TestObjectHana testObj;
89 testObj.number = 42;
90 testObj.number2 = 3.141592653589793;
91 testObj.numbers = { 1, 2, 3, 4 };
92 testObj.text = "test";
93 testObj.boolean = false;
94 CPPUNIT_ASSERT_EQUAL("{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}"s,
95 string(testObj.toJson().GetString()));
96}
97
102{
103 NestingObjectHana nestingObj;
104 nestingObj.name = "nesting";
105 TestObjectHana &testObj = nestingObj.testObj;
106 testObj.number = 42;
107 testObj.number2 = 3.141592653589793;
108 testObj.numbers = { 1, 2, 3, 4 };
109 testObj.text = "test";
110 testObj.boolean = false;
111 CPPUNIT_ASSERT_EQUAL(
112 "{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}}"s,
113 string(nestingObj.toJson().GetString()));
114 NestingArrayHana nestingArray;
115 nestingArray.name = "nesting2";
116 nestingArray.testObjects.emplace_back(testObj);
117 nestingArray.testObjects.emplace_back(testObj);
118 nestingArray.testObjects.back().number = 43;
119 CPPUNIT_ASSERT_EQUAL(
120 "{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},{\"number\":43,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}]}"s,
121 string(nestingArray.toJson().GetString()));
122}
123
128{
129 const TestObjectHana testObj(
130 TestObjectHana::fromJson("{\"number\":42,\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}"));
131
132 CPPUNIT_ASSERT_EQUAL(42, testObj.number);
133 CPPUNIT_ASSERT_EQUAL(3.141592653589793, testObj.number2);
134 CPPUNIT_ASSERT_EQUAL(vector<int>({ 1, 2, 3, 4 }), testObj.numbers);
135 CPPUNIT_ASSERT_EQUAL("test"s, testObj.text);
136 CPPUNIT_ASSERT_EQUAL(false, testObj.boolean);
137}
138
143{
144 const NestingObjectHana nestingObj(NestingObjectHana::fromJson("{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,"
145 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}}"));
146 const TestObjectHana &testObj = nestingObj.testObj;
147 CPPUNIT_ASSERT_EQUAL("nesting"s, nestingObj.name);
148 CPPUNIT_ASSERT_EQUAL(42, testObj.number);
149 CPPUNIT_ASSERT_EQUAL(3.141592653589793, testObj.number2);
150 CPPUNIT_ASSERT_EQUAL(vector<int>({ 1, 2, 3, 4 }), testObj.numbers);
151 CPPUNIT_ASSERT_EQUAL("test"s, testObj.text);
152 CPPUNIT_ASSERT_EQUAL(false, testObj.boolean);
153
154 const NestingArrayHana nestingArray(
155 NestingArrayHana::fromJson("{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,"
156 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},{\"number\":43,\"number2\":3."
157 "141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}]}"));
158 const vector<TestObjectHana> &testObjects = nestingArray.testObjects;
159 CPPUNIT_ASSERT_EQUAL("nesting2"s, nestingArray.name);
160 CPPUNIT_ASSERT_EQUAL(2_st, testObjects.size());
161 CPPUNIT_ASSERT_EQUAL(42, testObjects[0].number);
162 CPPUNIT_ASSERT_EQUAL(43, testObjects[1].number);
163 for (const TestObjectHana &nestedTestObj : testObjects) {
164 CPPUNIT_ASSERT_EQUAL(3.141592653589793, nestedTestObj.number2);
165 CPPUNIT_ASSERT_EQUAL(vector<int>({ 1, 2, 3, 4 }), nestedTestObj.numbers);
166 CPPUNIT_ASSERT_EQUAL("test"s, nestedTestObj.text);
167 CPPUNIT_ASSERT_EQUAL(false, nestedTestObj.boolean);
168 }
169}
170
175{
177 NestingArrayHana::fromJson("{\"name\":\"nesting2\",\"testObjects\":[{\"number\":42,\"number2\":3.141592653589793,"
178 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},{\"number\":43,\"number2\":3."
179 "141592653589793,\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false}]}",
180 &errors);
181 CPPUNIT_ASSERT_EQUAL(0_st, errors.size());
182
183 NestingObjectHana::fromJson("{\"name\":\"nesting\",\"testObj\":{\"number\":\"42\",\"number2\":3.141592653589793,\"numbers\":[1,2,3,4],\"text\":"
184 "\"test\",\"boolean\":false}}",
185 &errors);
186 CPPUNIT_ASSERT_EQUAL(1_st, errors.size());
187 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind);
188 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().expectedType);
189 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().actualType);
190 CPPUNIT_ASSERT_EQUAL("number"s, string(errors.front().member));
191 CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.front().record));
192 errors.clear();
193
194 NestingObjectHana::fromJson("{\"name\":\"nesting\",\"testObj\":{\"number\":42,\"number2\":3.141592653589793,\"numbers\":1,\"text\":"
195 "\"test\",\"boolean\":false}}",
196 &errors);
197 CPPUNIT_ASSERT_EQUAL(1_st, errors.size());
198 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind);
199 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().expectedType);
200 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors.front().actualType);
201 CPPUNIT_ASSERT_EQUAL("numbers"s, string(errors.front().member));
202 CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.front().record));
203 errors.clear();
204
205 NestingObjectHana::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors);
206 CPPUNIT_ASSERT_EQUAL(2_st, errors.size());
207 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.front().kind);
208 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.front().expectedType);
209 CPPUNIT_ASSERT_EQUAL(JsonType::Array, errors.front().actualType);
210 CPPUNIT_ASSERT_EQUAL("name"s, string(errors.front().member));
211 CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.front().record));
212 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors.back().kind);
213 CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors.back().expectedType);
214 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors.back().actualType);
215 CPPUNIT_ASSERT_EQUAL("testObj"s, string(errors.back().member));
216 CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors.back().record));
217 errors.clear();
218
219 const NestingArrayHana nestingArray(
220 NestingArrayHana::fromJson("{\"name\":\"nesting2\",\"testObjects\":[25,{\"number\":42,\"number2\":3.141592653589793,"
221 "\"numbers\":[1,2,3,4],\"text\":\"test\",\"boolean\":false},\"foo\",{\"number\":43,\"number2\":3."
222 "141592653589793,\"numbers\":[1,2,3,4,\"bar\"],\"text\":\"test\",\"boolean\":false}]}",
223 &errors));
224 CPPUNIT_ASSERT_EQUAL(3_st, errors.size());
225 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[0].kind);
226 CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[0].expectedType);
227 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[0].actualType);
228 CPPUNIT_ASSERT_EQUAL("testObjects"s, string(errors[0].member));
229 CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors[0].record));
230 CPPUNIT_ASSERT_EQUAL(0_st, errors[0].index);
231 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[1].kind);
232 CPPUNIT_ASSERT_EQUAL(JsonType::Object, errors[1].expectedType);
233 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[1].actualType);
234 CPPUNIT_ASSERT_EQUAL(2_st, errors[1].index);
235 CPPUNIT_ASSERT_EQUAL("testObjects"s, string(errors[1].member));
236 CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors[1].record));
237 CPPUNIT_ASSERT_EQUAL(JsonDeserializationErrorKind::TypeMismatch, errors[2].kind);
238 CPPUNIT_ASSERT_EQUAL(JsonType::Number, errors[2].expectedType);
239 CPPUNIT_ASSERT_EQUAL(JsonType::String, errors[2].actualType);
240 CPPUNIT_ASSERT_EQUAL("numbers"s, string(errors[2].member));
241 CPPUNIT_ASSERT_EQUAL("[document]"s, string(errors[2].record));
242 CPPUNIT_ASSERT_EQUAL(4_st, errors[2].index);
243 errors.clear();
244
245 errors.throwOn = JsonDeserializationErrors::ThrowOn::TypeMismatch;
246 CPPUNIT_ASSERT_THROW(NestingObjectHana::fromJson("{\"name\":[],\"testObj\":\"this is not an object\"}", &errors), JsonDeserializationError);
247}
The JsonReflectorBoostHanaTests class tests the integration of Boost.Hana with the RapidJSON wrapper.
void testDeserializeSimpleObjects()
Tests deserializing simple objects.
void testHandlingTypeMismatch()
Tests whether JsonDeserializationError is thrown on type mismatch.
void testSerializeSimpleObjects()
Tests serializing objects.
void testSerializeNestedObjects()
Tests serializing nested object and arrays.
void testDeserializeNestedObjects()
Tests deserializing nested objects and arrays.
Contains generic functions relying on Boost.Hana which can replace the code which would otherwise had...
Contains only the definition of the JsonSerializable template class which makes the reflection access...
CPPUNIT_TEST_SUITE_REGISTRATION(JsonReflectorBoostHanaTests)
The JsonDeserializationError struct describes any errors of fromJson() except such caused by invalid ...
The JsonDeserializationErrors struct can be passed to fromJson() for error handling.
enum ReflectiveRapidJSON::JsonDeserializationErrors::ThrowOn throwOn
The JsonSerializable class provides the CRTP-base for (de)serializable objects.