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 }