1 module jsonserialized.deserialization; 2 3 import std.conv; 4 import stdx.data.json; 5 import std.traits; 6 7 /// Deserialize the contents of a JSONValue into the specified array. 8 pure void deserializeFromJSONValue(T)(ref T array, in JSONValue jsonValue) if (isArray!T) { 9 alias ElementType = ForeachType!T; 10 11 // Iterate each item in the array JSONValue and add them to values, converting them to the actual type 12 foreach(jvItem; jsonValue.get!(JSONValue[])) { 13 static if (is(ElementType == struct)) { 14 // This item is a struct - instantiate it 15 ElementType newStruct; 16 17 // ...deserialize into the new instance 18 newStruct.deserializeFromJSONValue(jvItem); 19 20 // ...and add it to the array 21 array ~= newStruct; 22 } 23 else static if (is(ElementType == class)) { 24 // The item type is class - create a new instance 25 auto newClass = new ElementType(); 26 27 // ...deserialize into the new instance 28 newClass.deserializeFromJSONValue(jvItem); 29 30 // ...and add it to the array 31 array ~= newClass; 32 } 33 else static if (isSomeString!ElementType) { 34 array ~= jvItem.get!string.to!ElementType; 35 } 36 else static if (isArray!ElementType) { 37 // An array of arrays. Recursion time! 38 ElementType subArray; 39 40 subArray.deserializeFromJSONValue(jvItem); 41 array ~= subArray; 42 } 43 else { 44 array ~= jvItem.to!ElementType; 45 } 46 } 47 } 48 49 /// Deserialize the contents of a JSONValue into the specified associative array. 50 pure void deserializeFromJSONValue(T)(ref T associativeArray, in JSONValue jsonValue) if (isAssociativeArray!T) { 51 alias VType = ValueType!T; 52 53 // Iterate each item in the JSON object 54 foreach(stringKey, value; jsonValue.get!(JSONValue[string])) { 55 auto key = stringKey.to!(KeyType!T); 56 57 static if (isAssociativeArray!VType) { 58 /* The associative array's value type is another associative array type. 59 It's recursion time. */ 60 61 if (key in associativeArray) { 62 associativeArray[key].deserializeFromJSONValue(value); 63 } 64 else { 65 VType subAssocArray; 66 67 subAssocArray.deserializeFromJSONValue(value); 68 associativeArray[key] = subAssocArray; 69 } 70 } 71 else static if (is(VType == struct)) { 72 // The value type is a struct - instantiate it 73 VType newStruct; 74 75 // ...deserialize into the new instance 76 newStruct.deserializeFromJSONValue(value); 77 78 // ...and add it to the associative array 79 associativeArray[key] = newStruct; 80 } 81 else static if (is(VType == class)) { 82 // The value type is class - create a new instance 83 auto newClass = new VType(); 84 85 // ...deserialize into the new instance 86 newClass.deserializeFromJSONValue(value); 87 88 // ...and add it to the associative array 89 associativeArray[key] = newClass; 90 } 91 else static if (isSomeString!VType) { 92 string v; 93 94 if (value.hasType!string) 95 v = value.get!string; 96 else if (value.hasType!long) 97 v = value.get!long.to!string; 98 99 associativeArray[key] = v.to!VType; 100 } 101 else { 102 associativeArray[key] = value.to!VType; 103 } 104 } 105 } 106 107 /// Deserialize the contents of a JSONValue into the specified struct or class. 108 pure void deserializeFromJSONValue(T)(ref T obj, in JSONValue jsonValue) if (is(T == struct) || is(T == class)) { 109 enum fieldNames = FieldNameTuple!T; 110 111 foreach(fieldName; fieldNames) { 112 alias FieldType = typeof(__traits(getMember, obj, fieldName)); 113 114 if (fieldName !in jsonValue) { 115 continue; 116 } 117 118 static if (is(FieldType == struct)) { 119 // This field is a struct - recurse into it 120 __traits(getMember, obj, fieldName).deserializeFromJSONValue(jsonValue[fieldName]); 121 } 122 else static if (is(FieldType == class)) { 123 // This field is a class - recurse into it unless it is null 124 if (__traits(getMember, obj, fieldName) !is null) { 125 __traits(getMember, obj, fieldName).deserializeFromJSONValue(jsonValue[fieldName]); 126 } 127 } 128 else static if (isSomeString!FieldType) { 129 // If the JSONValue does not contain a string, don't try to deserialize 130 if (!jsonValue[fieldName].hasType!string) 131 continue; 132 133 // Because all string types are stored as string in JSONValue, get it as string and convert it to the correct string type 134 __traits(getMember, obj, fieldName) = jsonValue[fieldName].get!string.to!FieldType; 135 } 136 else static if (isArray!FieldType) { 137 // If the JSONValue does not contain an array, don't try to deserialize 138 if (!jsonValue[fieldName].hasType!(JSONValue[])) 139 continue; 140 141 // Field is an array 142 __traits(getMember, obj, fieldName).deserializeFromJSONValue(jsonValue[fieldName]); 143 } 144 else static if (isAssociativeArray!FieldType) { 145 // Field is an associative array 146 __traits(getMember, obj, fieldName).deserializeFromJSONValue(jsonValue[fieldName]); 147 } 148 else static if (isIntegral!FieldType) { 149 // If the JSONValue type does not contain a long, don't try to deserialize 150 if (!jsonValue[fieldName].hasType!long) 151 continue; 152 153 __traits(getMember, obj, fieldName) = jsonValue[fieldName].to!FieldType; 154 } 155 else { 156 __traits(getMember, obj, fieldName) = jsonValue[fieldName].to!FieldType; 157 } 158 } 159 } 160 161 /// Deserialize the contents of a JSONValue into a struct of type T, returning the newly created struct. 162 pure T deserializeFromJSONValue(T)(in JSONValue jsonValue) if (is(T == struct)) { 163 T obj; 164 165 obj.deserializeFromJSONValue(jsonValue); 166 return obj; 167 }