Report a bug
If you spot a problem with this page, click here to create a Github issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

asdf.serialization

ASDF and JSON Serialization

For aggregate types the order of the (de)serialization is the folowing: 1. All public fields of alias ? this that are not hidden by members of this (recursively). 2. All public fields of this. 3. All public properties of alias ? this that are not hidden by members of this (recursively). 4. All public properties of this.
Examples:
import std.bigint;
import std.datetime;
import std.conv;

enum E : char
{
	a,
	b,
	c,
}

static class C
{
	private double _foo;
pure:
	this()
	{
		_foo = 4;
	}

	double foo() const @property
	{
		return _foo + 10;
	}

	void foo(double d) @property
	{
		_foo = d - 10;
	}
}

static struct DateTimeProxy
{
	DateTime datetime;
	alias datetime this;

	static DateTimeProxy deserialize(Asdf data) pure
	{
		string val;
		deserializeScopedString(data, val);
		return DateTimeProxy(DateTime.fromISOString(val));
	}

	void serialize(S)(ref S serializer) pure
	{
		serializer.putValue(datetime.toISOString);
	}
}

static struct S
{
       static int staticNotSeialised = 5;
       enum int enumsNotSeialised = 3;

	@serializedAs!DateTimeProxy
	DateTime time;

	C object;

	string[E] map;

	@serializationKeys("bar_common", "bar")
	string bar;
}

enum json = `{"time":"20160304T000000","object":{"foo":14},"map":{"a":"A"},"bar_common":"escaped chars = '\\', '\"', '\t', '\r', '\n'"}`;
auto value = S(
	DateTime(2016, 3, 4),
	new C,
	[E.a : "A"],
	"escaped chars = '\\', '\"', '\t', '\r', '\n'");
assert(serializeToJson(value) == json, [getAllMembers!C].to!string);
assert(serializeToJson(cast(const)value) == json); // check serialization of const data
assert(serializeToAsdf(value).to!string == json);
assert(deserialize!S(json).serializeToJson == json);
Examples:
finalizeSerialization method
static struct S
{
	string a;
	int b;

	void finalizeSerialization(Serializer)(ref Serializer serializer)
	{
		serializer.putKey("c");
		serializer.putValue(100);
	}
}
assert(S("bar", 3).serializeToJson == `{"a":"bar","b":3,"c":100}`);
Examples:
finalizeDeserialization method
static struct S
{
	string a;
	int b;

	@serializationIgnoreIn
	double sum;

	void finalizeDeserialization(Asdf data) pure
	{
		auto r = data["c", "d"];
		auto a = r["e"].get(0.0);
		auto b = r["g"].get(0.0);
		sum = a + b;
	}
}
assert(`{"a":"bar","b":3,"c":{"d":{"e":6,"g":7}}}`.deserialize!S == S("bar", 3, 13));
Examples:
A user may define setter and/or getter properties.
static struct S
{
	@serializationIgnore string str;
pure:
	string a() @property
	{
		return str;
	}

	void b(int s) @property
	{
		str = s.to!string;
	}
}

assert(S("str").serializeToJson == `{"a":"str"}`);
assert(`{"b":123}`.deserialize!S.str == "123");
Examples:
Support for custom nullable types (types that has a bool property isNull, non-void property get returning payload and void property nullify that makes nullable type to null value)
static struct MyNullable
{
	long value;

	@property
	isNull() const
	{
		return value == 0;
	}

	@property
	get()
	{
		return value;
	}

	@property
	nullify()
	{
		value = 0;
	}

	auto opAssign(long value)
	{
		this.value = value;
	}
}

static struct Foo
{
	MyNullable my_nullable;
	string field;

	bool opEquals()(auto ref const(typeof(this)) rhs)
	{
		if (my_nullable.isNull && rhs.my_nullable.isNull)
			return field == rhs.field;

		if (my_nullable.isNull != rhs.my_nullable.isNull)
			return false;

		return my_nullable == rhs.my_nullable &&
			         field == rhs.field;
	}
}

static assert(isNullable!MyNullable);

Foo foo;
foo.field = "it's a foo";

assert (serializeToJson(foo) == `{"my_nullable":null,"field":"it's a foo"}`);

foo.my_nullable = 200;

assert (deserialize!Foo(`{"my_nullable":200,"field":"it's a foo"}`) == Foo(MyNullable(200), "it's a foo"));

import std.typecons : Nullable;
import std.stdio;

static struct Bar
{
	Nullable!long nullable;
	string field;

	bool opEquals()(auto ref const(typeof(this)) rhs)
	{
		if (nullable.isNull && rhs.nullable.isNull)
			return field == rhs.field;

		if (nullable.isNull != rhs.nullable.isNull)
			return false;

		return nullable == rhs.nullable &&
			         field == rhs.field;
	}
}

static assert(isNullable!(Nullable!(int)));
static assert(isNullable!(Nullable!(bool)));

Bar bar;
bar.field = "it's a bar";

assert (serializeToJson(bar) == `{"nullable":null,"field":"it's a bar"}`);

bar.nullable = 777;
assert (deserialize!Bar(`{"nullable":777,"field":"it's a bar"}`) == Bar(Nullable!long(777), "it's a bar"));
Examples:
Support for floating point nan and (partial) infinity
static struct Foo
{
	float f;

	bool opEquals()(auto ref const(typeof(this)) rhs)
	{
		import std.math : isNaN, approxEqual;

		if (f.isNaN && rhs.f.isNaN)
			return true;

		return approxEqual(f, rhs.f);
	}
}

// test for Not a Number
assert (serializeToJson(Foo()).to!string == `{"f":"nan"}`);
assert (serializeToAsdf(Foo()).to!string == `{"f":"nan"}`);

assert (deserialize!Foo(`{"f":null}`)  == Foo());
assert (deserialize!Foo(`{"f":"nan"}`) == Foo());

assert (serializeToJson(Foo(1f/0f)).to!string == `{"f":"inf"}`);
assert (serializeToAsdf(Foo(1f/0f)).to!string == `{"f":"inf"}`);
assert (deserialize!Foo(`{"f":"inf"}`)  == Foo( float.infinity));
assert (deserialize!Foo(`{"f":"-inf"}`) == Foo(-float.infinity));

assert (serializeToJson(Foo(-1f/0f)).to!string == `{"f":"-inf"}`);
assert (serializeToAsdf(Foo(-1f/0f)).to!string == `{"f":"-inf"}`);
assert (deserialize!Foo(`{"f":"-inf"}`) == Foo(-float.infinity));
  • class DeserializationException: asdf.asdf.AsdfException;
  • ubyte kind;
  • string func;
  • pure nothrow @nogc @safe this(ubyte kind, string msg = "Unexpected ASDF kind", string func = __PRETTY_FUNCTION__, string file = __FILE__, size_t line = __LINE__, Throwable next = null);
  • pure nothrow @nogc @safe this(ubyte kind, string msg, Throwable next, string func = __PRETTY_FUNCTION__, string file = __FILE__, size_t line = __LINE__);
  • string serializeToJson(V)(auto ref V value);
    JSON serialization function.
    Examples:
    struct S
    {
    	string foo;
    	uint bar;
    }
    
    assert(serializeToJson(S("str", 4)) == `{"foo":"str","bar":4}`);
    
  • string serializeToJsonPretty(string sep = "\x09", V)(auto ref V value);
    JSON serialization function with pretty formatting.
    Examples:
    static struct S { int a; }
    assert(S(4).serializeToJsonPretty == "{\n\t\"a\": 4\n}");
    
  • void serializeToJsonPretty(string sep = "\x09", V, O)(auto ref V value, ref O output)
    if (isOutputRange!(O, const(char)[]));
    JSON serialization function with pretty formatting and custom output range.
  • Asdf serializeToAsdf(V)(auto ref V value, size_t initialLength = 32);
    ASDF serialization function
    Examples:
    struct S
    {
    	string foo;
    	uint bar;
    }
    
    assert(serializeToAsdf(S("str", 4)).to!string == `{"foo":"str","bar":4}`);
    
  • V deserialize(V)(Asdf data);

    V deserialize(V)(in char[] str);
    Deserialization function
    Examples:
    Serializing struct Foo with disabled default ctor
    static struct Foo
    {
    	int i;
    
    	@disable
    	this();
    
    	this(int i)
    	{
    		this.i = i;
    	}
    
    	static auto deserialize(D)(auto ref D deserializer)
    	{
    		import asdf : deserialize;
    
    		foreach(elem; deserializer.byKeyValue)
    		{
    			switch(elem.key)
    			{
    				case "i":
    					int i = elem.value.to!int;
    					return typeof(this)(i);
    				default:
    			}
    		}
    
    		return typeof(this).init;
    	}
    }
    
    assert(deserialize!Foo(serializeToAsdf(Foo(6))) == Foo(6));
    
    Examples:
    struct S
    {
    	string foo;
    	uint bar;
    }
    
    assert(deserialize!S(`{"foo":"str","bar":4}`) == S("str", 4));
    
  • struct serializedAs(T);
    Serialization proxy for structs, classes, and enums.

    Example Proxy for types.

    @serializedAs!ProxyE
    enum E
    {
    	none,
    	bar,
    }
    
    // const(char)[] doesn't reallocate ASDF data.
    @serializedAs!(const(char)[])
    struct ProxyE
    {
    	E e;
    
    	this(E e)
    	{
    		this.e = e;
    	}
    
    	this(in char[] str)
    	{
    		switch(str)
    		{
    			case "NONE":
    			case "NA":
    			case "N/A":
    				e = E.none;
    				break;
    			case "BAR":
    			case "BR":
    				e = E.bar;
    				break;
    			default:
    				throw new Exception("Unknown: " ~ cast(string)str);
    		}
    	}
    
    	string toString()
    	{
    		if (e == E.none)
    			return "NONE";
    		else
    			return "BAR";
    	}
    
    	E opCast(T : E)()
    	{
    		return e;
    	}
    }
    
    unittest
    {
    	assert(serializeToJson(E.bar) == `"BAR"`);
    	assert(`"N/A"`.deserialize!E == E.none);
    	assert(`"NA"`.deserialize!E == E.none);
    }
    

    Examples:
    Proxy for members
    struct S
    {
    	// const(char)[] doesn't reallocate ASDF data.
    	@serializedAs!(const(char)[])
    	uint bar;
    }
    
    auto json = `{"bar":"4"}`;
    assert(serializeToJson(S(4)) == json);
    assert(deserialize!S(json) == S(4));
    
  • struct Serialization;
    Main serialization attribute type
  • string[] args;
    string list
  • struct SerializationGroup;
    Additional serialization attribute type
  • string[][] args;
    2D string list
  • pure @safe Serialization serializationKeys(string[] keys...);
    Attribute for key overloading during Serialization and Deserialization. The first argument overloads the key value during serialization unless serializationKeyOut is given.
    Examples:
    static struct S
    {
    	@serializationKeys("b", "a")
    	string s;
    }
    assert(`{"a":"d"}`.deserialize!S.serializeToJson == `{"b":"d"}`);
    
  • pure @safe Serialization serializationKeysIn(string[] keys...);
    Attribute for key overloading during deserialization.
    Examples:
    static struct S
    {
    	@serializationKeysIn("a")
    	string s;
    }
    assert(`{"a":"d"}`.deserialize!S.serializeToJson == `{"s":"d"}`);
    
  • enum Serialization serializationRequired;
    Attribute that force deserializer to throw an exception that the field was not found in the input.
    Examples:
    import std.exception;
    struct S
    {
    	@serializationRequired
    	string field;
    }
    assert(`{"field":"val"}`.deserialize!S.field == "val");
    assertThrown(`{"other":"val"}`.deserialize!S);
    
  • pure @safe SerializationGroup serializationMultiKeysIn(string[][] keys...);
    Attribute for key overloading during deserialization.

    AttentionserializationMultiKeysIn is not optimized yet and may significantly slowdown deserialization.

    Examples:
    static struct S
    {
    	@serializationMultiKeysIn(["a", "b", "c"])
    	string s;
    }
    assert(`{"a":{"b":{"c":"d"}}}`.deserialize!S.s == "d");
    
  • pure @safe Serialization serializationKeyOut(string key);
    Attribute for key overloading during serialization.
    Examples:
    static struct S
    {
    	@serializationKeyOut("a")
    	string s;
    }
    assert(`{"s":"d"}`.deserialize!S.serializeToJson == `{"a":"d"}`);
    
  • enum Serialization serializationIgnore;
    Attribute to ignore fields.
    Examples:
    static struct S
    {
    	@serializationIgnore
    	string s;
    }
    assert(`{"s":"d"}`.deserialize!S.s == null);
    assert(S("d").serializeToJson == `{}`);
    
  • enum Serialization serializationIgnoreIn;
    Attribute to ignore field during deserialization.
    Examples:
    static struct S
    {
    	@serializationIgnoreIn
    	string s;
    }
    assert(`{"s":"d"}`.deserialize!S.s == null);
    assert(S("d").serializeToJson == `{"s":"d"}`);
    
  • enum Serialization serializationIgnoreOut;
    Attribute to ignore field during serialization.
    Examples:
    static struct S
    {
    	@serializationIgnoreOut
    	string s;
    }
    assert(`{"s":"d"}`.deserialize!S.s == "d");
    assert(S("d").serializeToJson == `{}`);
    
  • enum Serialization serializationScoped;
    Can be applied only to strings fields. Does not allocate new data when deserializeing. Raw ASDF data is used for strings instead of new memory allocation. Use this attributes only for strings that would not be used after ASDF deallocation.
    Examples:
    import std.uuid;
    
    static struct S
    {
    	@serializationScoped
    	@serializedAs!string
    	UUID id;
    }
    assert(`{"id":"8AB3060E-2cba-4f23-b74c-b52db3bdfb46"}`.deserialize!S.id
    			== UUID("8AB3060E-2cba-4f23-b74c-b52db3bdfb46"));
    
  • enum Serialization serializationFlexible;
    Allows to use flexible deserialization rules the same way like Asdf.opCast does.
    See Also:
    .
    Examples:
    import std.uuid;
    
    static struct S
    {
    	@serializationFlexible
    	uint a;
    }
    
    assert(`{"a":"100"}`.deserialize!S.a == 100);
    assert(`{"a":true}`.deserialize!S.a == 1);
    assert(`{"a":null}`.deserialize!S.a == 0);
    
    Examples:
    static struct Vector
    {
    	@serializationFlexible int x;
    	@serializationFlexible int y;
    }
    
    auto json = `[{"x":"1","y":2},{"x":null, "y": null},{"x":1, "y":2}]`;
    auto decoded = json.deserialize!(Vector[]);
    import std.conv;
    assert(decoded == [Vector(1, 2), Vector(0, 0), Vector(1, 2)], decoded.text);
    
  • enum Serialization serializationLikeArray;
    Allows serialize / deserialize fields like arrays.
    A range or a container should be iterable for serialization. Following code should compile:
    foreach(ref value; yourRangeOrContainer)
    {
    	...
    }
    
    put(value) method is used for deserialization.
    Examples:
    import std.range;
    import std.uuid;
    
    static struct S
    {
    	private int count;
    	@serializationLikeArray
    	auto numbers() @property // uses `foreach`
    	{
    		return iota(count);
    	}
    
    	@serializationLikeArray
    	@serializedAs!string // input element type of
    	@serializationIgnoreOut
    	Appender!(string[]) strings; //`put` method is used
    }
    
    assert(S(5).serializeToJson == `{"numbers":[0,1,2,3,4]}`);
    assert(`{"strings":["a","b"]}`.deserialize!S.strings.data == ["a","b"]);
    
  • enum Serialization serializationLikeObject;
    Allows serialize / deserialize fields like objects.
    Object should have opApply method to allow serialization. Following code should compile:
    foreach(key, value; yourObject)
    {
    	...
    }
    
    Object should have only one opApply method with 2 argument to allow automatic value type deduction.
    opIndexAssign or opIndex is used for deserialization to support required syntax:
    yourObject["key"] = value;
    
    Multiple value types is supported for deserialization.
    Examples:
    static struct M
    {
    	private int sum;
    
    	// opApply is used for serialization
    	int opApply(int delegate(in char[] key, int val) pure dg) pure
    	{
    		if(auto r = dg("a", 1)) return r;
    		if(auto r = dg("b", 2)) return r;
    		if(auto r = dg("c", 3)) return r;
    		return 0;
    	}
    
    	// opIndexAssign for deserialization
    	void opIndexAssign(int val, string key) pure
    	{
    		sum += val;
    	}
    }
    
    static struct S
    {
    	@serializationLikeObject
    	@serializedAs!int
    	M obj;
    }
    
    assert(S.init.serializeToJson == `{"obj":{"a":1,"b":2,"c":3}}`);
    assert(`{"obj":{"a":1,"b":2,"c":9}}`.deserialize!S.obj.sum == 12);
    
  • struct serializationTransformIn(alias fun);

    struct serializationTransformOut(alias fun);
    Attributes for in and out transformations. Return type of in transformation must be implicitly convertable to the type of the field. Return type of out transformation may be differ from the type of the field. In transformation would be applied after serialization proxy if any. Out transformation would be applied before serialization proxy if any.
    Examples:
    // global unary function
    static int fin(int i)
    {
    	return i + 2;
    }
    
    static struct S
    {
    	@serializationTransformIn!fin
    	@serializationTransformOut!`"str".repeat.take(a).joiner("_").to!string`
    	int a;
    }
    
    auto s = deserialize!S(`{"a":3}`);
    assert(s.a == 5);
    assert(serializeToJson(s) == `{"a":"str_str_str_str_str"}`);
    
  • struct JsonSerializer(string sep, Dg);
    JSON serialization back-end
  • JsonBuffer!Dg sink;
    JSON string buffer
  • this(Dg sink);
  • uint objectBegin();

    void objectEnd(uint state);

    uint arrayBegin();

    void arrayEnd(uint state);

    void putEscapedKey(in char[] key);

    void putKey(in char[] key);

    void putNumberValue(Num)(Num num, FormatSpec!char fmt = FormatSpec!char.init);

    void putValue(typeof(null));

    void putValue(bool b);

    void putValue(in char[] str);

    void putValue(Num)(Num num)
    if (isNumeric!Num && !is(Num == enum));

    void elemBegin();

    void flush();
    Serialization primitives
  • auto jsonSerializer(string sep = "", Dg)(scope Dg sink);
    Creates JSON serialization back-end. Use sep equal to "\t" or " " for pretty formatting.
    Examples:
    import std.array;
    import std.bigint;
    
    auto app = appender!string;
    auto ser = jsonSerializer(&app.put!(const(char)[]));
    auto state0 = ser.objectBegin;
    
    	ser.putEscapedKey("null");
    	ser.putValue(null);
    
    	ser.putEscapedKey("array");
    	auto state1 = ser.arrayBegin();
    		ser.elemBegin; ser.putValue(null);
    		ser.elemBegin; ser.putValue(123);
    		ser.elemBegin; ser.putNumberValue(12300000.123, singleSpec("%.10e"));
    		ser.elemBegin; ser.putValue("\t");
    		ser.elemBegin; ser.putValue("\r");
    		ser.elemBegin; ser.putValue("\n");
    		ser.elemBegin; ser.putNumberValue(BigInt("1234567890"));
    	ser.arrayEnd(state1);
    
    ser.objectEnd(state0);
    ser.flush;
    
    assert(app.data == `{"null":null,"array":[null,123,1.2300000123e+07,"\t","\r","\n",1234567890]}`);
    
  • struct AsdfSerializer;
    ASDF serialization back-end
  • app
    OutputArray app;
    Output buffer
  • pure size_t objectBegin();

    pure void objectEnd(size_t state);

    pure size_t arrayBegin();

    pure void arrayEnd(size_t state);

    alias putEscapedKey = putKey;

    pure void putKey(in char[] key);

    pure void putNumberValue(Num)(Num num, FormatSpec!char fmt = FormatSpec!char.init);

    pure void putValue(typeof(null));

    pure void putValue(bool b);

    pure void putValue(in char[] str);

    void putValue(Num)(Num num)
    if (isNumeric!Num && !is(Num == enum));

    static pure void elemBegin();

    static pure void flush();
    Serialization primitives
  • auto asdfSerializer(size_t initialLength = 32);
    Create ASDF serialization back-end
    Examples:
    import std.bigint;
    
    auto ser = asdfSerializer();
    auto state0 = ser.objectBegin;
    
    	ser.putEscapedKey("null");
    	ser.putValue(null);
    
    	ser.putKey("array");
    	auto state1 = ser.arrayBegin();
    		ser.elemBegin; ser.putValue(null);
    		ser.elemBegin; ser.putValue(123);
    		ser.elemBegin; ser.putNumberValue(12300000.123, singleSpec("%.10e"));
    		ser.elemBegin; ser.putValue("\t");
    		ser.elemBegin; ser.putValue("\r");
    		ser.elemBegin; ser.putValue("\n");
    		ser.elemBegin; ser.putNumberValue(BigInt("1234567890"));
    	ser.arrayEnd(state1);
    
    ser.objectEnd(state0);
    
    assert(ser.app.result.to!string == `{"null":null,"array":[null,123,1.2300000123e+07,"\t","\r","\n",1234567890]}`);
    
  • void serializeValue(S)(ref S serializer, typeof(null));
    null value serialization
    Examples:
    assert(serializeToJson(null) == `null`);
    
  • void serializeValue(S, V)(ref S serializer, in V value, FormatSpec!char fmt = FormatSpec!char.init)
    if (isNumeric!V && !is(V == enum) || is(V == BigInt));
    Number serialization
    Examples:
    assert(serializeToJson(BigInt(123)) == `123`);
    assert(serializeToJson(2.40f) == `2.4`);
    assert(serializeToJson(float.nan) == `"nan"`);
    assert(serializeToJson(float.infinity) == `"inf"`);
    assert(serializeToJson(-float.infinity) == `"-inf"`);
    
  • void serializeValue(S, V)(ref S serializer, const V value)
    if (is(V == bool) && !is(V == enum));
    Boolean serialization
  • void serializeValue(S, V : char)(ref S serializer, const V value)
    if (is(V == char) && !is(V == enum));
    Char serialization
    Examples:
    assert(serializeToJson(true) == `true`);
    
  • void serializeValue(S, V)(ref S serializer, in V value)
    if (is(V == enum));
    Enum serialization
    Examples:
    enum Key { foo }
    assert(serializeToJson(Key.foo) == `"foo"`);
    
  • void serializeValue(S)(ref S serializer, in char[] value);
    String serialization
    Examples:
    assert(serializeToJson("\t \" \\") == `"\t \" \\"`);
    
  • void serializeValue(S, T)(ref S serializer, T[] value)
    if (!isSomeChar!T);
    Array serialization
  • void serializeValue(S, R)(ref S serializer, R value)
    if (isInputRange!R && !isSomeChar!(ElementType!R) && !isDynamicArray!R && !isNullable!R);
    Input range serialization
    Examples:
    input range serialization
    import std.algorithm : filter;
    
    struct Foo
    {
    	int i;
    }
    
    auto ar = [Foo(1), Foo(3), Foo(4), Foo(17)];
    
    auto filtered1 = ar.filter!"a.i & 1";
    auto filtered2 = ar.filter!"!(a.i & 1)";
    
    assert(serializeToJson(filtered1) == `[{"i":1},{"i":3},{"i":17}]`);
    assert(serializeToJson(filtered2) == `[{"i":4}]`);
    
    Examples:
    uint[2] ar = [1, 2];
    assert(serializeToJson(ar) == `[1,2]`);
    assert(serializeToJson(ar[]) == `[1,2]`);
    assert(serializeToJson(ar[0 .. 0]) == `[]`);
    assert(serializeToJson((uint[]).init) == `null`);
    
  • void serializeValue(S, T)(ref S serializer, auto ref T[string] value);
    String-value associative array serialization
    Examples:
    uint[string] ar = ["a" : 1];
    assert(serializeToJson(ar) == `{"a":1}`);
    ar.remove("a");
    assert(serializeToJson(ar) == `{}`);
    assert(serializeToJson((uint[string]).init) == `null`);
    
  • void serializeValue(S, V : const(T[K]), T, K)(ref S serializer, V value)
    if (is(K == enum));
    Enumeration-value associative array serialization
    Examples:
    enum E { a, b }
    uint[E] ar = [E.a : 1];
    assert(serializeToJson(ar) == `{"a":1}`);
    ar.remove(E.a);
    assert(serializeToJson(ar) == `{}`);
    assert(serializeToJson((uint[string]).init) == `null`);
    
  • void serializeValue(S, V : const(T[K]), T, K)(ref S serializer, V value)
    if (isIntegral!K && !is(K == enum));
    integral typed value associative array serialization
    Examples:
    uint[short] ar = [256 : 1];
    assert(serializeToJson(ar) == `{"256":1}`);
    ar.remove(256);
    assert(serializeToJson(ar) == `{}`);
    assert(serializeToJson((uint[string]).init) == `null`);
    assert(deserialize!(uint[short])(`{"256":1}`) == cast(uint[short]) [256 : 1]);
    
  • void serializeValue(S, N)(ref S serializer, auto ref N value)
    if (isNullable!N);
    Nullable type serialization
    Examples:
    import std.typecons;
    
    struct Nested
    {
    	float f;
    }
    
    struct T
    {
    	string str;
    	Nullable!Nested nested;
    }
    
    T t;
    assert(t.serializeToJson == `{"str":null,"nested":null}`);
    t.str = "txt";
    t.nested = Nested(123);
    assert(t.serializeToJson == `{"str":"txt","nested":{"f":123}}`);
    
  • void serializeValue(S, V)(ref S serializer, auto ref V value)
    if (!isNullable!V && isAggregateType!V && !is(V : BigInt) && !isInputRange!V);
    Struct and class type serialization
    Examples:
    Alias this support
    struct S
    {
        int u;
    }
    
    struct C
    {
        int b;
        S s;
        alias s this; 
    }
    
    assert(C(4, S(3)).serializeToJson == `{"u":3,"b":4}`);
    
    Examples:
    Custom serialize
    struct S
    {
    	void serialize(S)(ref S serializer)
    	{
    		auto state = serializer.objectBegin;
    		serializer.putEscapedKey("foo");
    		serializer.putValue("bar");
    		serializer.objectEnd(state);
    	}
    }
    enum json = `{"foo":"bar"}`;
    assert(serializeToJson(S()) == json);
    assert(serializeToAsdf(S()).to!string == json);
    
  • void deserializeValue(T : typeof(null))(Asdf data, T);
    Deserialize null value
    Examples:
    deserializeValue(serializeToAsdf(null), null);
    
  • pure @safe void deserializeValue(T : bool)(Asdf data, ref T value);
    Deserialize boolean value
    Examples:
    assert(deserialize!bool(serializeToAsdf(true)));
    assert(deserialize!bool(serializeToJson(true)));
    
  • void deserializeValue(V)(Asdf data, ref V value)
    if (isNumeric!V && !is(V == enum) || is(V == BigInt));
    Deserialize numeric value.

    Special deserialisation string values

    "+NAN"
    "+NaN"
    "+nan"
    "-NAN"
    "-NaN"
    "-nan"
    "NAN"
    "NaN"
    "nan"
    "+INF"
    "+Inf"
    "+inf"
    "-INF"
    "-Inf"
    "-inf"
    "INF"
    "Inf"
    "inf"
    "+NAN"
    "+NaN"
    "+nan"
    "-NAN"
    "-NaN"
    "-nan"
    "NAN"
    "NaN"
    "nan"
    "+INF"
    "+Inf"
    "+inf"
    "-INF"
    "-Inf"
    "-inf"
    "INF"
    "Inf"
    "inf"

    Examples:
    assert(deserialize!ulong (serializeToAsdf(20)) == ulong (20));
    assert(deserialize!ulong (serializeToJson(20)) == ulong (20));
    assert(deserialize!double(serializeToAsdf(20)) == double(20));
    assert(deserialize!double(serializeToJson(20)) == double(20));
    assert(deserialize!BigInt(serializeToAsdf(20)) == BigInt(20));
    assert(deserialize!BigInt(serializeToJson(20)) == BigInt(20));
    
    assert(deserialize!float (serializeToJson ("2.40")) == float (2.40));
    assert(deserialize!double(serializeToJson ("2.40")) == double(2.40));
    assert(deserialize!double(serializeToAsdf("-2.40")) == double(-2.40));
    
    import std.math : isNaN, isInfinity;
    assert(deserialize!float (serializeToJson  ("+NaN")).isNaN);
    assert(deserialize!float (serializeToJson  ("INF")).isInfinity);
    assert(deserialize!float (serializeToJson ("-inf")).isInfinity);
    
  • void deserializeValue(V)(Asdf data, ref V value)
    if (is(V == enum));
    Deserialize enum value
    Examples:
    enum Key { foo }
    assert(deserialize!Key(`"foo"`) == Key.foo);
    assert(deserialize!Key(serializeToAsdf("foo")) == Key.foo);
    
  • void deserializeScopedString(V : const(char)[])(Asdf data, ref V value);
    Deserializes scoped string value. This function does not allocate a new string and just make a raw cast of ASDF data.
  • void deserializeValue(V)(Asdf data, ref V value)
    if (is(V : const(char)[]) && !isAggregateType!V && !is(V == enum) && !isNullable!V);
    Deserializes string value. This function allocates new string.
    Examples:
    String enums supports both enum keys and enum values.
    enum SimpleEnum : string
    {
    	se1 = "se1value",
    	se2 = "se2value",
    	se3 = "se3value",
    }
    
    struct Simple
    {
    	SimpleEnum en;
    	SimpleEnum ex;
    }
    
    Simple simple = `{"en":"se2", "ex":"se3value"}`.deserialize!Simple;
       assert(simple.en == SimpleEnum.se2);
       assert(simple.ex == SimpleEnum.se3);
    
    Examples:
    issue #115
    import asdf;
    import std.typecons;
    
    struct Example
    {
    	Nullable!string field1;
    }
    
    assert(`{}`.deserialize!Example == Example());
    assert(Example().serializeToJson == `{"field1":null}`);
    
    Examples:
    assert(deserialize!string(serializeToJson(null)) is null);
    assert(deserialize!string(serializeToAsdf(null)) is null);
    assert(deserialize!string(serializeToJson("\tbar")) == "\tbar");
    assert(deserialize!string(serializeToAsdf("\"bar")) == "\"bar");
    
  • void deserializeValue(V)(Asdf data, ref V value)
    if (is(V == char) && !is(V == enum));
    Deserialize single char
    Examples:
    assert(deserialize!char(`"a"`) == 'a');
    assert(deserialize!byte(`-4`) == -4); // regression control
    
  • void deserializeValue(V : T[], T)(Asdf data, ref V value)
    if (!isSomeChar!T && !isStaticArray!V);
    Deserialize array
    Examples:
    assert(deserialize!(int[])(serializeToJson(null)) is null);
    assert(deserialize!(int[])(serializeToAsdf(null)) is null);
    assert(deserialize!(int[])(serializeToJson([1, 3, 4])) == [1, 3, 4]);
    assert(deserialize!(int[])(serializeToAsdf([1, 3, 4])) == [1, 3, 4]);
    
    Examples:
    static struct Foo
    {
    	int i;
    
    	@disable
    	this();
    
    	this(int i)
    	{
    		this.i = i;
    	}
    
    	static auto deserialize(D)(auto ref D deserializer)
    	{
    		import asdf : deserialize;
    
    		foreach(elem; deserializer.byKeyValue)
    		{
    			switch(elem.key)
    			{
    				case "i":
    					int i = elem.value.to!int;
    					return typeof(this)(i);
    				default:
    			}
    		}
    
    		return typeof(this).init;
    	}
    }
    
    assert(deserialize!(Foo[])(serializeToJson(null)) is null);
    assert(deserialize!(Foo[])(serializeToAsdf(null)) is null);
    assert(deserialize!(Foo[])(serializeToJson([Foo(1), Foo(3), Foo(4)])) == [Foo(1), Foo(3), Foo(4)]);
    assert(deserialize!(Foo[])(serializeToAsdf([Foo(1), Foo(3), Foo(4)])) == [Foo(1), Foo(3), Foo(4)]);
    
  • void deserializeValue(V : T[N], T, size_t N)(Asdf data, ref V value);
    Deserialize static array
    Examples:
    assert(deserialize!(int[4])(serializeToJson(null)) == [0, 0, 0, 0]);
    assert(deserialize!(int[4])(serializeToAsdf(null)) == [0, 0, 0, 0]);
    assert(deserialize!(int[4])(serializeToJson([1, 3, 4])) == [1, 3, 4, 0]);
    assert(deserialize!(int[4])(serializeToAsdf([1, 3, 4])) == [1, 3, 4, 0]);
    assert(deserialize!(int[2])(serializeToJson([1, 3, 4])) == [1, 3]);
    assert(deserialize!(int[2])(serializeToAsdf([1, 3, 4])) == [1, 3]);
    
    assert(deserialize!(char[2])(serializeToAsdf(['a','b'])) == ['a','b']);
    assert(deserialize!(char[2])(serializeToAsdf(['a','\0'])) == ['a','\0']);
    assert(deserialize!(char[2])(serializeToAsdf(['a','\255'])) == ['a','\255']);
    assert(deserialize!(char[2])(serializeToAsdf(['\255'])) == ['\255','\0']);
    assert(deserialize!(char[2])(serializeToAsdf(['\255', '\255', '\255'])) == ['\255','\255']);
    
    Examples:
    AA with value of aggregate type
    struct Foo
    {
    
    }
    
    assert (deserialize!(Foo[int])(serializeToJson([1: Foo()])) == [1:Foo()]);
    
  • void deserializeValue(V : T[string], T)(Asdf data, ref V value);
    Deserialize string-value associative array
    Examples:
    assert(deserialize!(int[string])(serializeToJson(null)) is null);
    assert(deserialize!(int[string])(serializeToAsdf(null)) is null);
    assert(deserialize!(int[string])(serializeToJson(["a" : 1, "b" : 2])) == ["a" : 1, "b" : 2]);
    assert(deserialize!(int[string])(serializeToAsdf(["a" : 1, "b" : 2])) == ["a" : 1, "b" : 2]);
    
  • void deserializeValue(V : T[E], T, E)(Asdf data, ref V value)
    if (is(E == enum));
    Deserialize enumeration-value associative array
    Examples:
    enum E {a, b}
    assert(deserialize!(int[E])(serializeToJson(null)) is null);
    assert(deserialize!(int[E])(serializeToAsdf(null)) is null);
    assert(deserialize!(int[E])(serializeToJson([E.a : 1, E.b : 2])) == [E.a : 1, E.b : 2]);
    assert(deserialize!(int[E])(serializeToAsdf([E.a : 1, E.b : 2])) == [E.a : 1, E.b : 2]);
    
  • void deserializeValue(V : T[K], T, K)(Asdf data, ref V value)
    if (isIntegral!K && !is(K == enum));
    Deserialize associative array with integral type key
    Examples:
    assert(deserialize!(int[int])(serializeToJson(null)) is null);
    assert(deserialize!(int[int])(serializeToAsdf(null)) is null);
    assert(deserialize!(int[int])(serializeToJson([2 : 1, 40 : 2])) == [2 : 1, 40 : 2]);
    assert(deserialize!(int[int])(serializeToAsdf([2 : 1, 40 : 2])) == [2 : 1, 40 : 2]);
    
  • void deserializeValue(V)(Asdf data, ref V value)
    if (isNullable!V);
    Deserialize Nullable value
    Examples:
    import std.typecons;
    
    struct Nested
    {
    	float f;
    }
    
    struct T
    {
    	string str;
    	Nullable!Nested nested;
    	Nullable!bool nval;
    }
    
    T t;
    assert(deserialize!T(`{"str":null,"nested":null}`) == t);
    t.str = "txt";
    t.nested = Nested(123);
    t.nval = false;
    assert(deserialize!T(`{"str":"txt","nested":{"f":123},"nval":false}`) == t);
    
  • void deserializeValue(V)(Asdf data, ref V value)
    if (!isNullable!V && isAggregateType!V && !is(V : BigInt));
    Deserialize aggregate value
    Examples:
    static class Turtle
    {
    	string _metadata;
    	long id;
    	string species;
    }
    
    auto turtles = `
       [{"_metadata":"xyz123", "id":72, "species":"Galapagos"},
    	{"_metadata":"tu144", "id":108, "species":"Snapping"},
    	null,
    	null,
    	{"_metadata":"anew1", "id":9314, "species":"Sea Turtle"}]`
      	.deserialize!(Turtle[]);
    
    Examples:
    Alias this support
    struct S
    {
        int a;
    }
    
    struct C
    {
        S s;
        alias s this; 
        int b;
    }
    
    assert(`{"a":3, "b":4}`.deserialize!C == C(S(3), 4));