1 module hjson.adapter; 2 3 package(hjson): 4 5 import std.json : JSONValue, JSONType, JSONException; 6 7 struct StdJsonSerializer 8 { 9 pure @system: 10 11 JSONValue* result; 12 13 uint objectBegin() 14 { 15 if(noRootAggregate) 16 { 17 result.object = null; 18 push(result); 19 } 20 else 21 { 22 JSONValue obj; 23 obj.object = null; 24 25 if(top.type == JSONType.object) 26 { 27 top.object[key] = obj; 28 push(&top.object[key]); 29 } 30 else 31 { 32 top.array ~= obj; 33 push(&top.array[$-1]); 34 } 35 } 36 return 0; 37 } 38 39 void objectEnd(uint state) 40 in(!noRootAggregate && top.type == JSONType.object) 41 { 42 pop(); 43 } 44 45 uint arrayBegin() 46 { 47 if(noRootAggregate) 48 { 49 result.array = []; 50 push(result); 51 } 52 else 53 { 54 JSONValue arr; 55 arr.array = []; 56 if(top.type == JSONType.object) 57 { 58 top.object[key] = arr; 59 push(&top.object[key]); 60 } 61 else 62 { 63 top.array ~= arr; 64 push(&top.array[$-1]); 65 } 66 } 67 return 0; 68 } 69 70 void arrayEnd(size_t state) 71 in(!noRootAggregate && top.type == JSONType.array) 72 { 73 pop(); 74 } 75 76 void putKey(const char[] key) 77 { 78 this.key = key; 79 } 80 void putValue(T)(T value) 81 { 82 if(noRootAggregate) 83 *result = value; 84 else if(top.type == JSONType.object) 85 top.object[key] = JSONValue(value); 86 else top.array ~= JSONValue(value); 87 } 88 void elemBegin() {} 89 void flush() {} 90 91 private: 92 93 void push(JSONValue* value){stack ~= value;} 94 ref inout(JSONValue) top() inout {return *(stack[$-1]);} 95 void pop() {stack.length = stack.length-1;} 96 bool noRootAggregate() const {return stack.length == 0;} 97 98 JSONValue*[] stack; 99 const(char)[] key; 100 101 invariant( 102 noRootAggregate || 103 top.type == JSONType.object || 104 top.type == JSONType.array 105 ); 106 } 107 108 version(unittest): 109 version(Have_unit_threaded): 110 111 import unit_threaded; 112 113 @("StdJsonSerializer") 114 unittest 115 { 116 import std.json : parseJSON, JSONValue; 117 118 JSONValue value; 119 auto ser = StdJsonSerializer(&value); 120 auto o = ser.objectBegin(); 121 ser.putKey("hello"); ser.putValue("world"); 122 ser.putKey("foo"); ser.putValue(1234); 123 ser.putKey("null"); ser.putValue(null); 124 ser.putKey("array"); 125 auto a = ser.arrayBegin(); 126 ser.elemBegin; ser.putValue(1); 127 ser.elemBegin; ser.putValue("abc"); 128 ser.elemBegin; ser.putValue(false); 129 ser.arrayEnd(a); 130 ser.putKey("afterArray"); ser.putValue(42); 131 ser.objectEnd(o); 132 133 value.should == parseJSON(q"< 134 { 135 "hello" : "world", 136 "foo" : 1234, 137 "null" : null, 138 "array" : [1, "abc", false], 139 "afterArray" : 42 140 } 141 >"); 142 }