jsonizer

Import all public modules for jsonizer.

Modules

common
module jsonizer.common
exceptions
module jsonizer.exceptions

Defines the exceptions that Jsonizer may throw.

fromjson
module jsonizer.fromjson

Contains functions for deserializing JSON data.

jsonize
module jsonizer.jsonize

Enables marking user-defined types for JSON serialization.

tojson
module jsonizer.tojson

Contains functions for serializing JSON data.

Examples

object serialization -- fields only

1 import std.math : approxEqual;
2 
3 static class Fields {
4   // classes must have a no-args constructor
5   // or a constructor marked with @jsonize (see later example)
6   this() { }
7 
8   this(int iVal, float fVal, string sVal, int[] aVal, string noJson) {
9     i = iVal;
10     f = fVal;
11     s = sVal;
12     a = aVal;
13     dontJsonMe = noJson;
14   }
15 
16   mixin JsonizeMe;
17 
18   @jsonize { // fields to jsonize -- test different access levels
19     public int i;
20     protected float f;
21     public int[] a;
22     private string s;
23   }
24   string dontJsonMe;
25 
26   override bool opEquals(Object o) {
27     auto other = cast(Fields) o;
28     return i == other.i && s == other.s && a == other.a && f.approxEqual(other.f);
29   }
30 }
31 
32 auto obj = new Fields(1, 4.2, "tally ho!", [9, 8, 7, 6], "blarg");
33 auto json = toJSON!Fields(obj);
34 
35 assert(json.object["i"].integer == 1);
36 assert(json.object["f"].floating.approxEqual(4.2));
37 assert(json.object["s"].str == "tally ho!");
38 assert(json.object["a"].array[0].integer == 9);
39 assert("dontJsonMe" !in json.object);
40 
41 // reconstruct from json
42 auto r = fromJSON!Fields(json);
43 assert(r.i == 1);
44 assert(r.f.approxEqual(4.2));
45 assert(r.s == "tally ho!");
46 assert(r.a == [9, 8, 7, 6]);
47 assert(r.dontJsonMe is null);
48 
49 // array of objects
50 auto a = [
51   new Fields(1, 4.2, "tally ho!", [9, 8, 7, 6], "blarg"),
52   new Fields(7, 42.2, "yea merrily", [1, 4, 6, 4], "asparagus")
53 ];
54 
55 // serialize array of user objects to json
56 auto jsonArray = toJSON!(Fields[])(a);
57 // reconstruct from json
58 assert(fromJSON!(Fields[])(jsonArray) == a);

object serialization with properties

1 import std.math : approxEqual;
2 
3 static class Props {
4   this() { } // class must have a no-args ctor
5 
6   this(int iVal, float fVal, string sVal, string noJson) {
7     _i = iVal;
8     _f = fVal;
9     _s = sVal;
10     _dontJsonMe = noJson;
11   }
12 
13   mixin JsonizeMe;
14 
15   @property {
16     // jsonize ref property accessing private field
17     @jsonize ref int i() { return _i; }
18     // jsonize property with non-trivial get/set methods
19     @jsonize float f() { return _f - 3; } // the jsonized value will equal _f - 3
20     float f(float val) { return _f = val + 5; } // 5 will be added to _f when retrieving from json
21     // don't jsonize these properties
22     ref string s() { return _s; }
23     ref string dontJsonMe() { return _dontJsonMe; }
24   }
25 
26   private:
27   int _i;
28   float _f;
29   @jsonize string _s;
30   string _dontJsonMe;
31 }
32 
33 auto obj = new Props(1, 4.2, "tally ho!", "blarg");
34 auto json = toJSON(obj);
35 
36 assert(json.object["i"].integer == 1);
37 assert(json.object["f"].floating.approxEqual(4.2 - 3.0)); // property should have subtracted 3 on retrieval
38 assert(json.object["_s"].str == "tally ho!");
39 assert("dontJsonMe" !in json.object);
40 
41 auto r = fromJSON!Props(json);
42 assert(r.i == 1);
43 assert(r._f.approxEqual(4.2 - 3.0 + 5.0)); // property accessor should add 5
44 assert(r._s == "tally ho!");
45 assert(r.dontJsonMe is null);

object serialization with custom constructor

1 import std.conv : to;
2 import std.json : parseJSON;
3 import std.math : approxEqual;
4 import jsonizer.tojson : toJSON;
5 
6 static class Custom {
7   mixin JsonizeMe;
8 
9   this(int i) {
10     _i = i;
11     _s = "something";
12     _f = 10.2;
13   }
14 
15   @jsonize this(int _i, string _s, float _f = 20.2) {
16     this._i = _i;
17     this._s = _s ~ " jsonized";
18     this._f = _f;
19   }
20 
21   @jsonize this(double d) { // alternate ctor
22     _f = d.to!float;
23     _s = d.to!string;
24     _i = d.to!int;
25   }
26 
27   private:
28   @jsonize {
29     string _s;
30     float _f;
31     int _i;
32   }
33 }
34 
35 auto c = new Custom(12);
36 auto json = toJSON(c);
37 assert(json.object["_i"].integer == 12);
38 assert(json.object["_s"].str == "something");
39 assert(json.object["_f"].floating.approxEqual(10.2));
40 auto c2 = fromJSON!Custom(json);
41 assert(c2._i == 12);
42 assert(c2._s == "something jsonized");
43 assert(c2._f.approxEqual(10.2));
44 
45 // test alternate ctor
46 json = parseJSON(`{"d" : 5}`);
47 c = json.fromJSON!Custom;
48 assert(c._f.approxEqual(5) && c._i == 5 && c._s == "5");

struct serialization

1 import std.math : approxEqual;
2 
3 static struct S {
4   mixin JsonizeMe;
5 
6   @jsonize {
7     int x;
8     float f;
9     string s;
10   }
11   int dontJsonMe;
12 
13   this(int x, float f, string s, int noJson) {
14     this.x = x;
15     this.f = f;
16     this.s = s;
17     this.dontJsonMe = noJson;
18   }
19 }
20 
21 auto s = S(5, 4.2, "bogus", 7);
22 auto json = toJSON(s); // serialize a struct
23 
24 assert(json.object["x"].integer == 5);
25 assert(json.object["f"].floating.approxEqual(4.2));
26 assert(json.object["s"].str == "bogus");
27 assert("dontJsonMe" !in json.object);
28 
29 auto r = fromJSON!S(json);
30 assert(r.x == 5);
31 assert(r.f.approxEqual(4.2));
32 assert(r.s == "bogus");
33 assert(r.dontJsonMe == int.init);

json file I/O

1 import std.file          : remove;
2 import jsonizer.fromjson : readJSON;
3 import jsonizer.tojson   : writeJSON;
4 
5 enum file = "test.json";
6 scope(exit) remove(file);
7 
8 static struct Data {
9   mixin JsonizeMe;
10 
11   @jsonize {
12     int x;
13     string s;
14     float f;
15   }
16 }
17 
18 // write an array of user-defined structs
19 auto array = [Data(5, "preposterous", 12.7), Data(8, "tesseract", -2.7), Data(5, "baby sloths", 102.7)];
20 file.writeJSON(array);
21 auto readBack = file.readJSON!(Data[]);
22 assert(readBack == array);
23 
24 // now try an associative array
25 auto aa = ["alpha": Data(27, "yams", 0), "gamma": Data(88, "spork", -99.999)];
26 file.writeJSON(aa);
27 auto aaReadBack = file.readJSON!(Data[string]);
28 assert(aaReadBack == aa);

inheritance

1 import std.math : approxEqual;
2 static class Parent {
3   mixin JsonizeMe;
4   @jsonize int x;
5   @jsonize string s;
6 }
7 
8 static class Child : Parent {
9   mixin JsonizeMe;
10   @jsonize float f;
11 }
12 
13 auto c = new Child;
14 c.x = 5;
15 c.s = "hello";
16 c.f = 2.1;
17 
18 auto json = c.toJSON;
19 assert(json.fromJSON!int("x") == 5);
20 assert(json.fromJSON!string("s") == "hello");
21 assert(json.fromJSON!float("f").approxEqual(2.1));
22 
23 auto child = json.fromJSON!Child;
24 assert(child !is null);
25 assert(child.x == 5 && child.s == "hello" && child.f.approxEqual(2.1));
26 
27 auto parent = json.fromJSON!Parent;
28 assert(parent.x == 5 && parent.s == "hello");

inheritance with ctors

1 import std.math : approxEqual;
2 static class Parent {
3   mixin JsonizeMe;
4 
5   @jsonize this(int x, string s) {
6     _x = x;
7     _s = s;
8   }
9 
10   @jsonize @property {
11     int x()    { return _x; }
12     string s() { return _s; }
13   }
14 
15   private:
16   int _x;
17   string _s;
18 }
19 
20 static class Child : Parent {
21   mixin JsonizeMe;
22 
23   @jsonize this(int x, string s, float f) {
24     super(x, s);
25     _f = f;
26   }
27 
28   @jsonize @property {
29     float f() { return _f; }
30   }
31 
32   private:
33   float _f;
34 }
35 
36 auto c = new Child(5, "hello", 2.1);
37 
38 auto json = c.toJSON;
39 assert(json.fromJSON!int("x") == 5);
40 assert(json.fromJSON!string("s") == "hello");
41 assert(json.fromJSON!float("f").approxEqual(2.1));
42 
43 auto child = json.fromJSON!Child;
44 assert(child.x == 5 && child.s == "hello" && child.f.approxEqual(2.1));
45 
46 auto parent = json.fromJSON!Parent;
47 assert(parent.x == 5 && parent.s == "hello");

renamed members

1 static class Bleh {
2   mixin JsonizeMe;
3   private {
4     @jsonize("x") int _x;
5     @jsonize("s") string _s;
6   }
7 }
8 
9 auto b = new Bleh;
10 b._x = 5;
11 b._s = "blah";
12 
13 auto json = b.toJSON;
14 
15 assert(json.fromJSON!int("x") == 5);
16 assert(json.fromJSON!string("s") == "blah");
17 
18 auto reconstruct = json.fromJSON!Bleh;
19 assert(reconstruct._x == b._x && reconstruct._s == b._s);

type inference

1 import std.json   : parseJSON;
2 import std.string : format;
3 import std.traits : fullyQualifiedName;
4 
5 static class TestComponent {
6   mixin JsonizeMe;
7   @jsonize int c;
8 }
9 
10 static class TestCompA : TestComponent {
11   mixin JsonizeMe;
12   @jsonize int a;
13 }
14 
15 static class TestCompB : TestComponent {
16   mixin JsonizeMe;
17   @jsonize string b;
18 }
19 
20 string classKeyA = fullyQualifiedName!TestCompA;
21 string classKeyB = fullyQualifiedName!TestCompB;
22 
23 auto data = `[
24   {
25     "class": "%s",
26     "c": 1,
27     "a": 5
28   },
29   {
30     "class": "%s",
31     "c": 2,
32     "b": "hello"
33   }
34 ]`.format(classKeyA, classKeyB).parseJSON.fromJSON!(TestComponent[]);
35 
36 auto a = cast(TestCompA) data[0];
37 auto b = cast(TestCompB) data[1];
38 
39 assert(a !is null && a.c == 1 && a.a == 5);
40 assert(b !is null && b.c == 2 && b.b == "hello");

type inference with custom type key

1 import std.string : format;
2 import std.traits : fullyQualifiedName;
3 
4 static class TestComponent {
5   mixin JsonizeMe;
6   @jsonize int c;
7 }
8 
9 static class TestCompA : TestComponent {
10   mixin JsonizeMe;
11   @jsonize int a;
12 }
13 
14 static class TestCompB : TestComponent {
15   mixin JsonizeMe;
16   @jsonize string b;
17 }
18 
19 // use "type" instead of "class" to identify dynamic type
20 JsonizeOptions options;
21 options.classKey = "type";
22 
23 // need to use these because unittest is assigned weird name
24 // normally would just be "modulename.classname"
25 string classKeyA = fullyQualifiedName!TestCompA;
26 string classKeyB = fullyQualifiedName!TestCompB;
27 
28 auto data = `[
29   {
30     "type": "%s",
31     "c": 1,
32     "a": 5
33   },
34   {
35     "type": "%s",
36     "c": 2,
37     "b": "hello"
38   }
39 ]`.format(classKeyA, classKeyB)
40 .fromJSONString!(TestComponent[])(options);
41 
42 auto a = cast(TestCompA) data[0];
43 auto b = cast(TestCompB) data[1];
44 assert(a !is null && a.c == 1 && a.a == 5);
45 assert(b !is null && b.c == 2 && b.b == "hello");

Meta

Date

Date: 3/23/15