1 /** 2 * Serialization utilities 3 */ 4 module jstruct.serializer; 5 6 import std.json; 7 import std.conv : to; 8 import std.traits : FieldTypeTuple, FieldNameTuple; 9 import std.traits : isArray; 10 11 /** 12 * Serializes the provided record into JSON 13 * 14 * Params: 15 * record = the record to serialize into 16 * Returns: A `JSONValue` containing the serialized record 17 */ 18 public JSONValue serializeRecord(RecordType)(RecordType record) 19 { 20 // Final JSON to submit 21 JSONValue builtJSON; 22 23 // Alias as to only expand later when used in compile-time 24 alias structTypes = FieldTypeTuple!(RecordType); 25 alias structNames = FieldNameTuple!(RecordType); 26 alias structValues = record.tupleof; 27 28 static foreach(cnt; 0..structTypes.length) 29 { 30 debug(dbg) 31 { 32 pragma(msg, structTypes[cnt]); 33 pragma(msg, structNames[cnt]); 34 // pragma(msg, structValues[cnt]); 35 } 36 37 static if(__traits(isSame, structTypes[cnt], int)) 38 { 39 builtJSON[structNames[cnt]] = structValues[cnt]; 40 } 41 else static if(__traits(isSame, structTypes[cnt], uint)) 42 { 43 builtJSON[structNames[cnt]] = structValues[cnt]; 44 } 45 else static if(__traits(isSame, structTypes[cnt], ulong)) 46 { 47 builtJSON[structNames[cnt]] = structValues[cnt]; 48 } 49 else static if(__traits(isSame, structTypes[cnt], long)) 50 { 51 builtJSON[structNames[cnt]] = structValues[cnt]; 52 } 53 else static if(__traits(isSame, structTypes[cnt], string)) 54 { 55 builtJSON[structNames[cnt]] = structValues[cnt]; 56 } 57 else static if(__traits(isSame, structTypes[cnt], JSONValue)) 58 { 59 builtJSON[structNames[cnt]] = structValues[cnt]; 60 } 61 else static if(__traits(isSame, structTypes[cnt], bool)) 62 { 63 builtJSON[structNames[cnt]] = structValues[cnt]; 64 } 65 else static if(isArray!(structTypes[cnt])) 66 { 67 builtJSON[structNames[cnt]] = structValues[cnt]; 68 } 69 else 70 { 71 debug(dbg) 72 { 73 pragma(msg, "Yaa"); 74 } 75 builtJSON[structNames[cnt]] = to!(string)(structValues[cnt]); 76 } 77 } 78 79 80 return builtJSON; 81 } 82 83 // Test serialization of a struct to JSON 84 85 86 version(unittest) 87 { 88 import std.algorithm.searching : canFind; 89 import std.string : cmp; 90 import std.stdio : writeln; 91 } 92 93 /** 94 * Example serialization of our struct 95 * `Person` to JSON 96 */ 97 unittest 98 { 99 enum EnumType 100 { 101 DOG, 102 CAT 103 } 104 105 struct Person 106 { 107 public string firstname, lastname; 108 public int age; 109 public string[] list; 110 public JSONValue extraJSON; 111 public EnumType eType; 112 } 113 114 Person p1; 115 p1.firstname = "Tristan"; 116 p1.lastname = "Kildaire"; 117 p1.age = 23; 118 p1.list = ["1", "2", "3"]; 119 p1.extraJSON = parseJSON(`{"item":1, "items":[1,2,3]}`); 120 p1.eType = EnumType.CAT; 121 122 JSONValue serialized = serializeRecord(p1); 123 124 string[] keys = serialized.object().keys(); 125 assert(canFind(keys, "firstname") && cmp(serialized["firstname"].str(), "Tristan") == 0); 126 assert(canFind(keys, "lastname") && cmp(serialized["lastname"].str(), "Kildaire") == 0); 127 assert(canFind(keys, "age") && serialized["age"].integer() == 23); 128 129 assert(canFind(keys, "list")); 130 JSONValue[] elems = serialized["list"].array(); 131 for(ulong i = 0; i < elems.length; i++) 132 { 133 string curElem = elems[i].str(); 134 assert(curElem == p1.list[i]); 135 } 136 137 debug(dbg) 138 { 139 writeln(serialized.toPrettyString()); 140 } 141 }