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: Ilya Yaroshenko 
10 Macros:
11 +/
12 module mir.algebraic_alias.json;
13 
14 import mir.algebraic: TaggedVariant, This;
15 public import mir.string_map: StringMap;
16 
17 /++
18 Definition union for $(LREF JsonAlgebraic).
19 +/
20 union JsonAlgebraicUnion
21 {
22     ///
23     typeof(null) null_;
24     ///
25     bool boolean;
26     ///
27     long integer;
28     ///
29     double float_;
30     ///
31     immutable(char)[] string;
32     /// Self alias in array.
33     This[] array;
34     /// Self alias in $(MREF mir,string_map).
35     StringMap!This object;
36 }
37 
38 /++
39 JSON tagged algebraic alias.
40 
41 The example below shows only the basic features. Advanced API to work with algebraic types can be found at $(GMREF mir-core, mir,algebraic).
42 See also $(MREF mir,string_map) - ordered string-value associative array.
43 +/
44 alias JsonAlgebraic = TaggedVariant!JsonAlgebraicUnion;
45 
46 ///
47 unittest
48 {
49     import mir.ndslice.topology: map;
50     import mir.array.allocation: array;
51 
52     JsonAlgebraic value;
53 
54     StringMap!JsonAlgebraic object;
55 
56     // Default
57     assert(value.isNull);
58     assert(value.kind == JsonAlgebraic.Kind.null_);
59 
60     // Boolean
61     value = object["bool"] = true;
62     assert(!value.isNull);
63     assert(value == true);
64     assert(value.kind == JsonAlgebraic.Kind.boolean);
65     assert(value.get!bool == true);
66     assert(value.get!(JsonAlgebraic.Kind.boolean) == true);
67 
68     // Null
69     value = object["null"] = null;
70     assert(value.isNull);
71     assert(value == null);
72     assert(value.kind == JsonAlgebraic.Kind.null_);
73     assert(value.get!(typeof(null)) == null);
74     assert(value.get!(JsonAlgebraic.Kind.null_) == null);
75 
76     // String
77     value = object["string"] = "s";
78     assert(value.kind == JsonAlgebraic.Kind..string);
79     assert(value == "s");
80     assert(value.get!string == "s");
81     assert(value.get!(JsonAlgebraic.Kind..string) == "s");
82 
83     // Integer
84     value = object["integer"] = 4;
85     assert(value.kind == JsonAlgebraic.Kind.integer);
86     assert(value == 4);
87     assert(value != 4.0);
88     assert(value.get!long == 4);
89     assert(value.get!(JsonAlgebraic.Kind.integer) == 4);
90 
91     // Float
92     value = object["float"] = 3.0;
93     assert(value.kind == JsonAlgebraic.Kind.float_);
94     assert(value != 3);
95     assert(value == 3.0);
96     assert(value.get!double == 3.0);
97     assert(value.get!(JsonAlgebraic.Kind.float_) == 3.0);
98 
99     // Array
100     JsonAlgebraic[] arr = [0, 1, 2, 3, 4].map!JsonAlgebraic.array;
101 
102     value = object["array"] = arr;
103     assert(value.kind == JsonAlgebraic.Kind.array);
104     assert(value == arr);
105     assert(value.get!(JsonAlgebraic[])[3] == 3);
106 
107     // Object
108     assert(object.keys == ["bool", "null", "string", "integer", "float", "array"]);
109     object.values[0] = "false";
110     assert(object["bool"] == "false"); // it is a string now
111     object.remove("bool"); // remove the member
112 
113     value = object["array"] = object;
114     assert(value.kind == JsonAlgebraic.Kind.object);
115     assert(value.get!(StringMap!JsonAlgebraic).keys is object.keys);
116     assert(value.get!(StringMap!JsonAlgebraic).values is object.values);
117 
118     JsonAlgebraic[string] aa = object.toAA;
119     object = StringMap!JsonAlgebraic(aa);
120 
121     JsonAlgebraic fromAA = ["a" : JsonAlgebraic(3), "b" : JsonAlgebraic("b")];
122     assert(fromAA.get!(StringMap!JsonAlgebraic)["a"] == 3);
123     assert(fromAA.get!(StringMap!JsonAlgebraic)["b"] == "b");
124 }