1 module jsonserialized.unittests;
2 
3 unittest {
4     import dunit.toolkit : assertEqual;
5 
6     import jsonserialized.serialization : serializeToJSONValue;
7     import jsonserialized.deserialization : deserializeFromJSONValue;
8     import stdx.data.json : toJSONValue;
9 
10     struct TestSubStruct {
11         int anotherInt;
12         string anotherString;
13     }
14 
15     struct TestStruct {
16         struct NestedStruct {
17             int nestedInt;
18             string nestedString;
19         }
20 
21         int singleInt;
22         float singleFloat;
23         int[] intArray;
24         int[][] arrayOfIntArrays;
25         int[string] intStringAssocArray;
26         int[int] intIntAssocArray;
27         char singleChar;
28         char[] charArray;
29         string singleString;
30         string[] stringArray;
31         string[][] arrayOfStringArrays;
32         string[string] stringAssocArray;
33         string[string][string] stringAssocArrayOfAssocArrays;
34         bool trueBool;
35         bool falseBool;
36 
37         TestSubStruct subStruct;
38         NestedStruct nestedStruct;
39         NestedStruct[] arrayOfNestedStructs;
40         NestedStruct[string] nestedStructAssocArray;
41     }
42 
43     // Create test struct and set it up with some test values
44     TestStruct ts;
45     with (ts) {
46         singleInt = 1234;
47         singleFloat = 1.234;
48         intArray = [1, 2, 3, 4];
49         arrayOfIntArrays = [[1, 2], [3, 4]];
50         intStringAssocArray = ["one": 1, "two": 2, "three": 3];
51         intIntAssocArray = [1: 3, 2: 1, 3: 2];
52         singleChar = 'A';
53         charArray = ['A', 'B', 'C', 'D'];
54         singleString = "just a string";
55         stringArray = ["a", "few", "strings"];
56         arrayOfStringArrays = [["a", "b"], ["c", "d"]];
57         stringAssocArray = ["a": "A", "b": "B", "c": "C"];
58         stringAssocArrayOfAssocArrays = ["a": ["a": "A", "b": "B"], "b": ["c": "C", "d": "D"]];
59         trueBool = true;
60         falseBool = false;
61         subStruct.anotherInt = 42;
62         subStruct.anotherString = "Another string";
63         nestedStruct.nestedInt = 53;
64         nestedStruct.nestedString = "Nested string";
65         arrayOfNestedStructs = [NestedStruct(1, "One"), NestedStruct(2, "Two")];
66         nestedStructAssocArray = ["one": NestedStruct(1, "One"), "two": NestedStruct(2, "Two")];
67     }
68 
69     // Serialize the struct to JSON
70     auto jv = ts.serializeToJSONValue();
71 
72     // Create a new empty struct
73     TestStruct ts2;
74 
75     // Deserialize the JSONValue into it
76     ts2.deserializeFromJSONValue(jv);
77 
78     // Assert that both structs are identical
79     assertEqual(ts2.singleInt, ts.singleInt);
80     assertEqual(ts2.singleFloat, ts.singleFloat);
81     assertEqual(ts2.intArray, ts.intArray);
82     assertEqual(ts2.arrayOfIntArrays, ts.arrayOfIntArrays);
83     assertEqual(ts2.intStringAssocArray, ts.intStringAssocArray);
84     assertEqual(ts2.intIntAssocArray, ts.intIntAssocArray);
85     assertEqual(ts2.singleChar, ts.singleChar);
86     assertEqual(ts2.charArray, ts.charArray);
87     assertEqual(ts2.singleString, ts.singleString);
88     assertEqual(ts2.stringArray, ts.stringArray);
89     assertEqual(ts2.arrayOfStringArrays, ts.arrayOfStringArrays);
90     assertEqual(ts2.stringAssocArray, ts.stringAssocArray);
91     assertEqual(ts2.stringAssocArrayOfAssocArrays, ts.stringAssocArrayOfAssocArrays);
92     assertEqual(ts2.trueBool, ts.trueBool);
93     assertEqual(ts2.falseBool, ts.falseBool);
94     assertEqual(ts2.subStruct, ts.subStruct);
95     assertEqual(ts2.subStruct.anotherInt, ts.subStruct.anotherInt);
96     assertEqual(ts2.subStruct.anotherString, ts.subStruct.anotherString);
97     assertEqual(ts2.nestedStruct, ts.nestedStruct);
98     assertEqual(ts2.nestedStruct.nestedInt, ts.nestedStruct.nestedInt);
99     assertEqual(ts2.nestedStruct.nestedString, ts.nestedStruct.nestedString);
100     assertEqual(ts2.arrayOfNestedStructs, ts.arrayOfNestedStructs);
101     assertEqual(ts2.arrayOfNestedStructs[0].nestedInt, ts.arrayOfNestedStructs[0].nestedInt);
102     assertEqual(ts2.arrayOfNestedStructs[0].nestedString, ts.arrayOfNestedStructs[0].nestedString);
103     assertEqual(ts2.arrayOfNestedStructs[1].nestedInt, ts.arrayOfNestedStructs[1].nestedInt);
104     assertEqual(ts2.arrayOfNestedStructs[1].nestedString, ts.arrayOfNestedStructs[1].nestedString);
105     assertEqual(ts2.nestedStructAssocArray, ts.nestedStructAssocArray);
106     assertEqual(ts2.nestedStructAssocArray["one"].nestedInt, ts.nestedStructAssocArray["one"].nestedInt);
107     assertEqual(ts2.nestedStructAssocArray["two"].nestedString, ts.nestedStructAssocArray["two"].nestedString);
108 
109     // Attempt to deserialize partial JSON
110     TestStruct ts3;
111     ts3.deserializeFromJSONValue(`{ "singleInt": 42, "singleString": "Don't panic." }`.toJSONValue());
112 
113     ts3.singleInt.assertEqual(42);
114     ts3.singleString.assertEqual("Don't panic.");
115 
116     // Attempt to deserialize JSON containing a property that does not exist in the struct
117     TestStruct ts4;
118     ts4.deserializeFromJSONValue(`{ "nonexistentString": "Move along, nothing to see here." }`.toJSONValue());
119 
120     auto ts5 = deserializeFromJSONValue!TestStruct(`{ "singleInt": 42, "singleString": "Don't panic." }`.toJSONValue());
121     ts5.singleInt.assertEqual(42);
122     ts5.singleString.assertEqual("Don't panic.");
123 }
124 
125 unittest {
126     import dunit.toolkit : assertEqual;
127 
128     import jsonserialized.serialization : serializeToJSONValue;
129     import jsonserialized.deserialization : deserializeFromJSONValue;
130     import stdx.data.json : toJSONValue;
131 
132     class TestSubClass {
133         int anotherInt;
134     }
135 
136     class TestClass {
137         static class NestedClass {
138             int nestedInt;
139 
140             pure this() {
141             }
142 
143             this(in int initInt) {
144                 nestedInt = initInt;
145             }
146         }
147 
148         int singleInt;
149         float singleFloat;
150         int[] intArray;
151         int[][] arrayOfIntArrays;
152         int[string] intStringAssocArray;
153         int[int] intIntAssocArray;
154         char singleChar;
155         char[] charArray;
156         string singleString;
157         string[] stringArray;
158         string[][] arrayOfStringArrays;
159         string[string] stringAssocArray;
160         string[string][string] stringAssocArrayOfAssocArrays;
161         NestedClass[] arrayOfNestedClasses;
162         NestedClass[string] nestedClassAssocArray;
163 
164         auto subClass = new TestSubClass();
165         auto nestedClass = new NestedClass(53);
166     }
167 
168     // Create test struct and set it up with some test values
169     auto tc = new TestClass();
170     with (tc) {
171         singleInt = 1234;
172         singleFloat = 1.234;
173         intArray = [1, 2, 3, 4];
174         arrayOfIntArrays = [[1, 2], [3, 4]];
175         intStringAssocArray = ["one": 1, "two": 2, "three": 3];
176         intIntAssocArray = [1: 3, 2: 1, 3: 2];
177         singleChar = 'A';
178         charArray = ['A', 'B', 'C', 'D'];
179         singleString = "just a string";
180         stringArray = ["a", "few", "strings"];
181         arrayOfStringArrays = [["a", "b"], ["c", "d"]];
182         stringAssocArray = ["a": "A", "b": "B", "c": "C"];
183         stringAssocArrayOfAssocArrays = ["a": ["a": "A", "b": "B"], "b": ["c": "C", "d": "D"]];
184         arrayOfNestedClasses = [new NestedClass(1), new NestedClass(2)];
185         nestedClassAssocArray = ["one": new NestedClass(1), "two": new NestedClass(2)];
186         subClass.anotherInt = 42;
187     }
188 
189     // Serialize the struct to JSON
190     auto jv = tc.serializeToJSONValue();
191 
192     // Create a new empty struct
193     auto tc2 = new TestClass();
194 
195     // Deserialize the JSONValue into it
196     tc2.deserializeFromJSONValue(jv);
197 
198     // Assert that both structs are identical
199     assertEqual(tc2.singleInt, tc.singleInt);
200     assertEqual(tc2.singleFloat, tc.singleFloat);
201     assertEqual(tc2.intArray, tc.intArray);
202     assertEqual(tc2.arrayOfIntArrays, tc.arrayOfIntArrays);
203     assertEqual(tc2.intStringAssocArray, tc.intStringAssocArray);
204     assertEqual(tc2.intIntAssocArray, tc.intIntAssocArray);
205     assertEqual(tc2.singleChar, tc.singleChar);
206     assertEqual(tc2.charArray, tc.charArray);
207     assertEqual(tc2.singleString, tc.singleString);
208     assertEqual(tc2.stringArray, tc.stringArray);
209     assertEqual(tc2.arrayOfStringArrays, tc.arrayOfStringArrays);
210     assertEqual(tc2.stringAssocArray, tc.stringAssocArray);
211     assertEqual(tc2.stringAssocArrayOfAssocArrays, tc.stringAssocArrayOfAssocArrays);
212     assertEqual(tc2.subClass.anotherInt, tc.subClass.anotherInt);
213     assertEqual(tc2.nestedClass.nestedInt, tc.nestedClass.nestedInt);
214     assertEqual(tc2.arrayOfNestedClasses[0].nestedInt, tc.arrayOfNestedClasses[0].nestedInt);
215     assertEqual(tc2.arrayOfNestedClasses[1].nestedInt, tc.arrayOfNestedClasses[1].nestedInt);
216     assertEqual(tc2.nestedClassAssocArray["one"].nestedInt, tc.nestedClassAssocArray["one"].nestedInt);
217     assertEqual(tc2.nestedClassAssocArray["two"].nestedInt, tc.nestedClassAssocArray["two"].nestedInt);
218 }
219 
220 unittest {
221     import dunit.toolkit : assertEqual;
222 
223     import jsonserialized.deserialization : deserializeFromJSONValue;
224     import stdx.data.json : toJSONValue;
225 
226     string[string] aa;
227     auto jsonValue = `{ "aString": "theString", "anInt": 42 }`.toJSONValue();
228 
229     aa.deserializeFromJSONValue(jsonValue);
230 
231     assertEqual(aa["aString"], "theString");
232     assertEqual(aa["anInt"], "42");
233 }
234 
235 unittest {
236     /* Unit tests for attempting to deserialize mismatching types */
237     import dunit.toolkit : assertEqual;
238 
239     import jsonserialized.deserialization : deserializeFromJSONValue;
240     import stdx.data.json : toJSONValue;
241 
242     struct TestStruct {
243         int intValue;
244         string stringValue;
245         int notArray;
246         string alsoNotArray;
247         int notAA;
248         string alsoNotAA;
249     }
250 
251     auto jsonValue = `{ "intValue": "aString", "stringValue": 42, "notArray": [], "alsoNotArray": [], "notAA": {}, "alsoNotAA": {} }`.toJSONValue();
252 
253     TestStruct ts;
254     ts.deserializeFromJSONValue(jsonValue);
255 
256     assertEqual(ts.intValue, 0);
257     assertEqual(ts.stringValue, "");
258     assertEqual(ts.notArray, 0);
259     assertEqual(ts.alsoNotArray, "");
260     assertEqual(ts.notAA, 0);
261     assertEqual(ts.alsoNotAA, "");
262 }