1 module ToJson; 2 3 import dyaml; 4 import std.algorithm; 5 import std.format; 6 import std.json; 7 import std.range : empty; 8 import std.typecons; 9 10 JSONValue toJson(const Node node, Flag!"ordered" ordered) 11 { 12 final switch (node.type) with (NodeType) { 13 case null_: return JSONValue(null_); 14 case merge: assert(false); 15 case boolean: return JSONValue(node.get!bool); 16 case integer: return JSONValue(node.get!int); 17 case decimal: return JSONValue(node.get!double); 18 case binary: return JSONValue(node.get!int); 19 case timestamp: return JSONValue(node.get!(.string)); 20 case string: return JSONValue(node.get!(.string)); 21 case mapping: 22 if (ordered) 23 { 24 // Make an array, to preserve order. 25 JSONValue[] result; 26 foreach (.string key, const Node value; node) 27 { 28 result ~= JSONValue(["key": JSONValue(key), "value": value.toJson(ordered)]); 29 } 30 return JSONValue(result); 31 } 32 else 33 { 34 JSONValue[.string] result; 35 foreach (.string key, const Node value; node) 36 { 37 result[key] = value.toJson(ordered); 38 } 39 return JSONValue(result); 40 } 41 case sequence: 42 JSONValue[] result; 43 foreach (const Node value; node) 44 { 45 result ~= value.toJson(ordered); 46 } 47 return JSONValue(result); 48 case invalid: 49 assert(false); 50 } 51 } 52 53 bool hasKey(JSONValue table, string[] keys...) 54 in (table.isTable) 55 in (!keys.empty) 56 { 57 if (!table.array.any!(a => a["key"] == JSONValue(keys[0]))) 58 { 59 return false; 60 } 61 if (keys.length == 1) 62 { 63 return true; 64 } 65 return table.getEntry(keys[0]).hasKey(keys[1 .. $]); 66 } 67 68 JSONValue getEntry(JSONValue table, string key) 69 in (table.isTable) 70 { 71 foreach (value; table.array) 72 { 73 if (value["key"].str == key) 74 { 75 return value["value"]; 76 } 77 } 78 assert(false, format!"No key %s in table %s"(key, table)); 79 } 80 81 JSONValue toObject(JSONValue table) 82 in (table.isTable) 83 { 84 JSONValue[string] result; 85 foreach (value; table.array) 86 { 87 result[value["key"].str] = value["value"]; 88 } 89 return JSONValue(result); 90 } 91 92 bool isTable(JSONValue value) 93 { 94 return value.type == JSONType.array && value.array.all!( 95 a => a.type == JSONType.object && a.object.length == 2 96 && "key" in a && "value" in a && a["key"].type == JSONType..string); 97 }