Reflection for RapidJSON  0.0.15
Reflection for serializing/deserializing with RapidJSON
jsonreflector-boosthana.cpp
Go to the documentation of this file.
1 #include "../json/reflector-boosthana.h"
2 #include "../json/serializable.h"
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 
9 using 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 
21 using namespace std;
22 using namespace CPPUNIT_NS;
23 using namespace RAPIDJSON_NAMESPACE;
24 using namespace CppUtilities;
25 using namespace CppUtilities::Literals;
26 using namespace ReflectiveRapidJSON;
27 
29 
30 // define some structs for testing serialization
31 struct TestObjectHana : public JsonSerializable<TestObjectHana> {
32  BOOST_HANA_DEFINE_STRUCT(TestObjectHana, (int, number), (double, number2), (vector<int>, numbers), (string, text), (bool, boolean));
33 };
34 
35 struct NestingObjectHana : public JsonSerializable<NestingObjectHana> {
36  BOOST_HANA_DEFINE_STRUCT(NestingObjectHana, (string, name), (TestObjectHana, testObj));
37 };
38 
39 struct NestingArrayHana : public JsonSerializable<NestingArrayHana> {
40  BOOST_HANA_DEFINE_STRUCT(NestingArrayHana, (string, name), (vector<TestObjectHana>, testObjects));
41 };
42 
44 
49 class 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 
58 public:
59  void setUp() override;
60  void tearDown() override;
61 
63  void testSerializeSimpleObjects();
64  void testSerializeNestedObjects();
66  void testDeserializeSimpleObjects();
67  void testDeserializeNestedObjects();
68  void testHandlingTypeMismatch();
69 
70 private:
71 };
72 
74 
76 {
77 }
78 
80 {
81 }
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 &testObj : testObjects) {
164  CPPUNIT_ASSERT_EQUAL(3.141592653589793, testObj.number2);
165  CPPUNIT_ASSERT_EQUAL(vector<int>({ 1, 2, 3, 4 }), testObj.numbers);
166  CPPUNIT_ASSERT_EQUAL("test"s, testObj.text);
167  CPPUNIT_ASSERT_EQUAL(false, testObj.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 }
ReflectiveRapidJSON::JsonDeserializationErrors
The JsonDeserializationErrors struct can be passed to fromJson() for error handling.
Definition: errorhandling.h:154
JsonReflectorBoostHanaTests::testSerializeNestedObjects
void testSerializeNestedObjects()
Tests serializing nested object and arrays.
Definition: jsonreflector-boosthana.cpp:101
ReflectiveRapidJSON::JsonReflector::fromJson
Type fromJson(const char *json, std::size_t jsonSize, JsonDeserializationErrors *errors=nullptr)
Deserializes the specified JSON to.
Definition: reflector.h:1059
JsonReflectorBoostHanaTests::tearDown
void tearDown() override
Definition: jsonreflector-boosthana.cpp:79
JsonReflectorBoostHanaTests::testSerializePrimitives
void testSerializePrimitives()
JsonReflectorBoostHanaTests
The JsonReflectorBoostHanaTests class tests the integration of Boost.Hana with the RapidJSON wrapper.
Definition: jsonreflector-boosthana.cpp:49
JsonReflectorBoostHanaTests::testSerializeSimpleObjects
void testSerializeSimpleObjects()
Tests serializing objects.
Definition: jsonreflector-boosthana.cpp:86
ReflectiveRapidJSON
Definition: traits.h:13
CPPUNIT_TEST_SUITE_REGISTRATION
CPPUNIT_TEST_SUITE_REGISTRATION(JsonReflectorBoostHanaTests)
JsonReflectorBoostHanaTests::setUp
void setUp() override
Definition: jsonreflector-boosthana.cpp:75
JsonReflectorBoostHanaTests::testDeserializePrimitives
void testDeserializePrimitives()
ReflectiveRapidJSON::JsonSerializable
The JsonSerializable class provides the CRTP-base for (de)serializable objects.
Definition: reflector.h:33
ReflectiveRapidJSON::JsonDeserializationError
The JsonDeserializationError struct describes any errors of fromJson() except such caused by invalid ...
Definition: errorhandling.h:109
JsonReflectorBoostHanaTests::testHandlingTypeMismatch
void testHandlingTypeMismatch()
Tests whether JsonDeserializationError is thrown on type mismatch.
Definition: jsonreflector-boosthana.cpp:174
ReflectiveRapidJSON::JsonDeserializationErrors::throwOn
enum ReflectiveRapidJSON::JsonDeserializationErrors::ThrowOn throwOn
JsonReflectorBoostHanaTests::testDeserializeNestedObjects
void testDeserializeNestedObjects()
Tests deserializing nested objects and arrays.
Definition: jsonreflector-boosthana.cpp:142
JsonReflectorBoostHanaTests::testDeserializeSimpleObjects
void testDeserializeSimpleObjects()
Tests deserializing simple objects.
Definition: jsonreflector-boosthana.cpp:127