The OpenD Programming Language

1 /++
2 $(H1 Mutable JSON value)
3 
4 This module contains a single alias definition and doesn't provide JSON serialization API.
5 
6 See_also: JSON libraries $(MIR_PACKAGE mir-ion) and $(MIR_PACKAGE asdf);
7 
8 License: $(HTTP www.apache.org/licenses/LICENSE-2.0, Apache-2.0)
9 Authors: Ilia Ki 
10 Macros:
11 +/
12 module mir.algebraic_alias.json;
13 
14 import mir.algebraic: Algebraic, This;
15 ///
16 public import mir.string_map: StringMap;
17 
18 /++
19 Definition union for $(LREF JsonAlgebraic).
20 +/
21 union Json_
22 {
23     ///
24     typeof(null) null_;
25     ///
26     bool boolean;
27     ///
28     long integer;
29     ///
30     double float_;
31     ///
32     immutable(char)[] string;
33     /// Self alias in array.
34     This[] array;
35     /// Self alias in $(MREF mir,string_map).
36     StringMap!This object;
37 }
38 
39 /++
40 JSON tagged algebraic alias.
41 
42 The example below shows only the basic features. Advanced API to work with algebraic types can be found at $(GMREF mir-core, mir,algebraic).
43 See also $(MREF mir,string_map) - ordered string-value associative array.
44 +/
45 alias JsonAlgebraic = Algebraic!Json_;
46 
47 ///
48 version(mir_test)
49 @safe pure
50 unittest
51 {
52     import mir.test: should;
53     import mir.ndslice.topology: map;
54     import mir.array.allocation: array;
55 
56     JsonAlgebraic value;
57 
58     StringMap!JsonAlgebraic object;
59 
60     // Default
61     assert(value.isNull);
62     assert(value.kind == JsonAlgebraic.Kind.null_);
63 
64     // Boolean
65     value = object["bool"] = true;
66     assert(!value.isNull);
67     assert(value == true);
68     assert(value.kind == JsonAlgebraic.Kind.boolean);
69     // access
70     assert(value.boolean == true);
71     assert(value.get!bool == true);
72     assert(value.get!"boolean" == true);
73     assert(value.get!(JsonAlgebraic.Kind.boolean) == true);
74     // nothrow access
75     assert(value.trustedGet!bool == true);
76     assert(value.trustedGet!"boolean" == true);
77     assert(value.trustedGet!(JsonAlgebraic.Kind.boolean) == true);
78     // checks
79     assert(!value._is!string);
80     assert(value._is!bool);
81     assert(value._is!"boolean");
82     assert(value._is!(JsonAlgebraic.Kind.boolean));
83 
84     // Null
85     value = object["null"] = null;
86     assert(value.isNull);
87     assert(value == null);
88     assert(value.kind == JsonAlgebraic.Kind.null_);
89     // access
90     assert(value.null_ == null);
91     assert(value.get!(typeof(null)) == null);
92     assert(value.get!(JsonAlgebraic.Kind.null_) == null);
93 
94     // String
95     value = object["string"] = "s";
96     assert(value.kind == JsonAlgebraic.Kind..string);
97     assert(value == "s");
98     // access
99     // Yep, `string` here is an alias to `get!(immutable(char)[])` method
100     assert(value..string == "s");
101     // `string` here is an alias of type `immutable(char)[]`
102     assert(value.get!string == "s");
103     assert(value.get!"string" == "s");
104     // finally, `string` here is an enum meber
105     assert(value.get!(JsonAlgebraic.Kind..string) == "s");
106 
107     // Integer
108     value = object["integer"] = 4;
109     assert(value.kind == JsonAlgebraic.Kind.integer);
110     assert(value == 4);
111     assert(value != 4.0);
112     assert(value.integer == 4);
113 
114     // Float
115     value = object["float"] = 3.0;
116     assert(value.kind == JsonAlgebraic.Kind.float_);
117     assert(value != 3);
118     assert(value == 3.0);
119     assert(value.float_ == 3.0);
120 
121     // Array
122     JsonAlgebraic[] arr = [0, 1, 2, 3, 4].map!JsonAlgebraic.array;
123 
124     value = object["array"] = arr;
125     assert(value.kind == JsonAlgebraic.Kind.array);
126     assert(value == arr);
127     assert(value.array[3] == 3);
128 
129     // Object
130     assert(object.keys == ["bool", "null", "string", "integer", "float", "array"]);
131     object.values[0] = "false";
132     assert(object["bool"] == "false"); // it is a string now
133     object.remove("bool"); // remove the member
134 
135     value = object["array"] = object;
136     assert(value.kind == JsonAlgebraic.Kind.object);
137     assert(value.object.keys is object.keys);
138 
139     JsonAlgebraic[string] aa = object.toAA;
140     object = aa.StringMap!JsonAlgebraic;
141 
142     JsonAlgebraic fromAA = ["a" : JsonAlgebraic(3), "b" : JsonAlgebraic("b")];
143     assert(fromAA.object["a"] == 3);
144     assert(fromAA.object["b"] == "b");
145 
146     // object foreach iteration
147     long sum;
148     foreach (ref key, ref val; fromAA.object)
149         if (key == "a")
150             sum += val.get!long;
151     sum.should == 3;
152 }