1 module libpb.deserialization; 2 3 import std.json; 4 import std.traits : FieldTypeTuple, FieldNameTuple; 5 6 public RecordType fromJSON(RecordType)(JSONValue jsonIn) 7 { 8 RecordType record; 9 10 // Alias as to only expand later when used in compile-time 11 alias structTypes = FieldTypeTuple!(RecordType); 12 alias structNames = FieldNameTuple!(RecordType); 13 alias structValues = record.tupleof; 14 15 static foreach(cnt; 0..structTypes.length) 16 { 17 debug(dbg) 18 { 19 pragma(msg, structTypes[cnt]); 20 pragma(msg, structNames[cnt]); 21 // pragma(msg, structValues[cnt]); 22 } 23 24 static if(__traits(isSame, mixin(structTypes[cnt]), byte)) 25 { 26 mixin("record."~structNames[cnt]) = cast(byte)jsonIn[structNames[cnt]].integer(); 27 } 28 else static if(__traits(isSame, mixin(structTypes[cnt]), ubyte)) 29 { 30 mixin("record."~structNames[cnt]) = cast(ubyte)jsonIn[structNames[cnt]].uinteger(); 31 } 32 else static if(__traits(isSame, mixin(structTypes[cnt]), short)) 33 { 34 mixin("record."~structNames[cnt]) = cast(short)jsonIn[structNames[cnt]].integer(); 35 } 36 else static if(__traits(isSame, mixin(structTypes[cnt]), ushort)) 37 { 38 mixin("record."~structNames[cnt]) = cast(ushort)jsonIn[structNames[cnt]].uinteger(); 39 } 40 else static if(__traits(isSame, mixin(structTypes[cnt]), int)) 41 { 42 mixin("record."~structNames[cnt]) = cast(int)jsonIn[structNames[cnt]].integer(); 43 } 44 else static if(__traits(isSame, mixin(structTypes[cnt]), uint)) 45 { 46 mixin("record."~structNames[cnt]) = cast(uint)jsonIn[structNames[cnt]].uinteger(); 47 } 48 else static if(__traits(isSame, mixin(structTypes[cnt]), ulong)) 49 { 50 mixin("record."~structNames[cnt]) = cast(ulong)jsonIn[structNames[cnt]].uinteger(); 51 } 52 else static if(__traits(isSame, mixin(structTypes[cnt]), long)) 53 { 54 mixin("record."~structNames[cnt]) = cast(long)jsonIn[structNames[cnt]].integer(); 55 } 56 else static if(__traits(isSame, mixin(structTypes[cnt]), string)) 57 { 58 mixin("record."~structNames[cnt]) = jsonIn[structNames[cnt]].str(); 59 60 debug(dbg) 61 { 62 pragma(msg,"record."~structNames[cnt]); 63 } 64 } 65 else static if(__traits(isSame, mixin(structTypes[cnt]), JSONValue)) 66 { 67 mixin("record."~structNames[cnt]) = jsonIn[structNames[cnt]]; 68 69 debug(dbg) 70 { 71 pragma(msg,"record."~structNames[cnt]); 72 } 73 } 74 else static if(__traits(isSame, mixin(structTypes[cnt]), bool)) 75 { 76 mixin("record."~structNames[cnt]) = jsonIn[structNames[cnt]].boolean(); 77 78 debug(dbg) 79 { 80 pragma(msg,"record."~structNames[cnt]); 81 } 82 } 83 //FIXME: Not sure how to get array support going, very new to meta programming 84 else static if(__traits(isSame, mixin(structTypes[cnt]), mixin(structTypes[cnt])[])) 85 { 86 mixin("record."~structNames[cnt]) = jsonIn[structNames[cnt]].boolean(); 87 88 debug(dbg) 89 { 90 pragma(msg,"record."~structNames[cnt]); 91 } 92 } 93 else 94 { 95 // throw new 96 //TODO: Throw error 97 debug(dbg) 98 { 99 pragma(msg, "Unknown type for de-serialization"); 100 } 101 } 102 } 103 104 return record; 105 } 106 107 unittest 108 { 109 import std.string : cmp; 110 import std.stdio : writeln; 111 112 struct Person 113 { 114 public string firstname, lastname; 115 public int age; 116 public bool isMale; 117 public JSONValue obj; 118 public int[] list; 119 } 120 121 JSONValue json = parseJSON(`{ 122 "firstname" : "Tristan", 123 "lastname": "Kildaire", 124 "age": 23, 125 "obj" : {"bruh":1}, 126 "isMale": true, 127 "list": [1,2,3] 128 } 129 `); 130 131 Person person = fromJSON!(Person)(json); 132 133 debug(dbg) 134 { 135 writeln(person); 136 } 137 138 assert(cmp(person.firstname, "Tristan") == 0); 139 assert(cmp(person.lastname, "Kildaire") == 0); 140 assert(person.age == 23); 141 assert(person.isMale == true); 142 assert(person.obj["bruh"].integer() == 1); 143 //TODO: list test case 144 }