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.

mir.serde

This implements common de/serialization routines.
License:
Authors:
Ilya Yaroshenko
class SerdeException: object.Exception;
Serde Exception
pure nothrow @nogc @safe this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null);
pure nothrow @nogc @safe this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__);
class SerdeMirException: mir.serde.SerdeException;
Serde Exception with formatting support
struct SerdeAnnotated(T, string annotation);
Constructs annotated type.
T value;
enum SerdeTarget: int;
Helper enumeration for for serializer . Use negative int values for user defined targets.
ion
json
cbor
msgpack
yaml
csv
excel
bloomberg
typedJson
struct serdeKeys;
Attribute for key overloading during Serialization and Deserialization. The first argument overloads the key value during serialization unless serdeKeyOut is given.
immutable(string)[] keys;
pure nothrow @nogc @trusted this(immutable(string)[] keys...);
struct serdeKeyOut;
Attribute for key overloading during serialization.
string key;
pure nothrow @nogc @safe this(string key);
enum serdeRegister;
The attribute should be used as a hind for scripting languages to register type deserializer in the type system.
The attribute should be applied to a type definition.
enum serdeAnnotation;
The attribute can be applied to a string-like member that should be de/serialized as an annotation / attribute.
Also, the attribute can be applied on a type to denote that the type should be used to de/serialize annotated value.
This feature is used in mir-ion.
template isAnnotated(T)
Checks if the type marked with serdeAnnotation.
template serdeGetAnnotationMembersIn(T)
Examples:
struct S
{
    double data;

    @serdeAnnotation
    string a;
    @serdeAnnotation @serdeIgnoreIn
    string b;
    @serdeAnnotation @serdeIgnoreOut
    string c;
    @serdeAnnotation @serdeIgnore
    string d;
}

static assert(serdeGetAnnotationMembersIn!int == []);
static assert(serdeGetAnnotationMembersIn!S == ["a", "c"]);
template serdeGetAnnotationMembersOut(T)
Examples:
struct S
{
    double data;

    @serdeAnnotation
    string a;
    @serdeAnnotation @serdeIgnoreIn
    string b;
    @serdeAnnotation @serdeIgnoreOut
    string c;
    @serdeAnnotation @serdeIgnore
    string d;
    @serdeAnnotation enum string e = "e";
    static @serdeAnnotation string f() @safe pure nothrow @nogc @property {
        return "f";
    }
}

static assert(serdeGetAnnotationMembersOut!int == []);
static assert(serdeGetAnnotationMembersOut!S == ["a", "b", "f"]);
struct serdeAlgebraicAnnotation;
An annotation / attribute for algebraic types deserialization.
This feature is used in mir-ion for mir.algebraic.
string annotation;
pure nothrow @nogc @safe this(string annotation);
template serdeHasAlgebraicAnnotation(T)
template serdeGetAlgebraicAnnotation(T)
template serdeDynamicAlgebraic(alias getAlgebraicDeserializerByAnnotation)
User defined attribute used to attach a function that returns a deserialization delegate.
The attribute is usefull for scripting languages and dynamic algebraic types.
Examples:
static struct _global
{
    alias Deserializer = S delegate(string s, ubyte[] data) @safe pure;
    Deserializer getDeserializer(string name) { return map[name]; }
    Deserializer[string] map;

    @serdeDynamicAlgebraic!getDeserializer
    struct S {}

    static assert(serdeIsDynamicAlgebraic!S);
    static assert(__traits(isSame, serdeGetAlgebraicDeserializer!S, getDeserializer));
}
template serdeIsDynamicAlgebraic(T)
template serdeGetAlgebraicDeserializer(T)
template serdeGetKeysIn(alias symbol)

pure nothrow @nogc @trusted immutable(string)[] serdeGetKeysIn(T)(const T value)
if (is(T == enum));
Returns:
immutable array of the input keys for the symbol or enum value
Examples:
struct S
{
    int f;

    @serdeKeys("D", "t")
    int d;

    @serdeIgnore
    int i;

    @serdeIgnoreIn
    int ii;

    @serdeIgnoreOut
    int io;

    void p(int) @property {}
}

static assert(serdeGetKeysIn!(S.f) == ["f"]);
static assert(serdeGetKeysIn!(S.d) == ["D", "t"]);
static assert(serdeGetKeysIn!(S.i) == null);
static assert(serdeGetKeysIn!(S.ii) == null);
static assert(serdeGetKeysIn!(S.io) == ["io"]);
static assert(serdeGetKeysIn!(S.p) == ["p"]);
Examples:
enum E
{
    @serdeKeys("A", "alpha")
    a,
    @serdeKeys("B", "beta")
    b,
    c,
}

static assert (serdeGetKeysIn(E.a) == ["A", "alpha"], serdeGetKeysIn(E.a));
static assert (serdeGetKeysIn(E.c) == ["c"]);
template serdeGetKeyOut(alias symbol)

pure nothrow @nogc @safe string serdeGetKeyOut(T)(const T value)
if (is(T == enum));
Returns:
output key for the symbol or enum value
Examples:
struct S
{
    int f;

    @serdeKeys("D", "t")
    int d;

    @serdeIgnore
    int i;

    @serdeIgnoreIn
    int ii;

    @serdeIgnoreOut
    int io;

    @serdeKeys("P")
    @serdeKeyOut("")
    void p(int) @property {}
}

static assert(serdeGetKeyOut!(S.f) == "f");
static assert(serdeGetKeyOut!(S.d) == "D");
static assert(serdeGetKeyOut!(S.i) is null);
static assert(serdeGetKeyOut!(S.ii) == "ii");
static assert(serdeGetKeyOut!(S.io) is null);
static assert(serdeGetKeyOut!(S.p) !is null);
static assert(serdeGetKeyOut!(S.p) == "");
Examples:
enum E
{
    @serdeKeys("A", "alpha")
    a,
    @serdeKeys("B", "beta")
    @serdeKeyOut("o")
    b,
    c,
}

static assert (serdeGetKeyOut(E.a) == "A");
static assert (serdeGetKeyOut(E.b) == "o");
static assert (serdeGetKeyOut(E.c) == "c");
enum serdeIgnore;
Attribute to ignore field.
enum serdeIgnoreIn;
Attribute to ignore field during deserialization.
enum serdeIgnoreOut;
Attribute to ignore field during serialization.
enum serdeIgnoreDefault;
Attribute to ignore a field during deserialization when equals to its default value. Do not use it on void initialized fields or aggregates with void initialized fields, recursively.
Examples:
struct S
{
    @serdeIgnoreDefault
    double d = 0; // skips field if 0 during deserialization
}

import std.traits: hasUDA;

static assert(hasUDA!(S.d, serdeIgnoreDefault));
struct serdeProxy(T);
Serialization proxy.
Examples:
import mir.small_string;

struct S
{
    @serdeProxy!(SmallString!32)
    double d;
}

import std.traits: hasUDA;

static assert(hasUDA!(S.d, serdeProxy));
static assert(hasUDA!(S.d, serdeProxy!(SmallString!32)));
static assert(is(serdeGetProxy!(S.d) == SmallString!32));
template serdeGetProxy(alias symbol)
enum serdeScopeStringProxy;
Can be applied only to fields that can be constructed from strings. Does not allocate new data when deserializeing. Raw data is used for strings instead of new memory allocation. Use this attributes only for strings that would not be used after the input data deallocation.
struct serdeIgnoreOutIf(alias pred);
Attributes to conditional ignore field during serialization.
The predicate should be aplied to the member, to the aggregate type.
template serdeGetIgnoreOutIf(alias symbol)
struct serdeIgnoreOutIfAggregate(alias pred);
Attributes to conditional ignore field during serialization.
The predicate should be aplied to the aggregate value, not to the member.
template serdeGetIgnoreOutIfAggregate(alias symbol)
struct serdeIgnoreInIfAggregate(alias pred);
Attributes to conditional ignore field during deserialization.
The attribute should be combined with serdeRealOrderedIn applied on the aggregate.
template serdeGetIgnoreInIfAggregate(alias symbol)
struct serdeIgnoreIfAggregate(alias pred);
Attributes to conditional ignore field during serialization and deserialization.
The attribute should be combined with serdeRealOrderedIn applied on the aggregate.
The predicate should be aplied to the aggregate value, not to the member.
template serdeGetIgnoreIfAggregate(alias symbol)
enum serdeFlexible;
Allows to use flexible deserialization rules such as conversion from input string to numeric types.
enum serdeLikeList;
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.
enum serdeLikeStruct;
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.
enum serdeFallbackStruct;
The attribute is used for algebraic deserialization for types like Variant!(string, S) @serdeFallbackStruct struct S {}
enum serdeFields;
Force serialize / deserialize on fields instead of Range API.
enum serdeIgnoreCase;
Ignore keys for object and enum members. Should be applied to members or enum type itself.
bool hasSerdeIgnoreCase(T)(T value)
if (is(T == enum));
Examples:
enum E
{
    @serdeIgnoreCase
    a,
    b,
    @serdeIgnoreCase
    c,
    d,
}

static assert(hasSerdeIgnoreCase(E.a));
static assert(!hasSerdeIgnoreCase(E.b));
static assert(hasSerdeIgnoreCase(E.c));
static assert(!hasSerdeIgnoreCase(E.d));
Examples:
@serdeIgnoreCase
enum E
{
    a,
    b,
    c,
    d,
}

static assert(hasSerdeIgnoreCase(E.a));
static assert(hasSerdeIgnoreCase(E.b));
static assert(hasSerdeIgnoreCase(E.c));
static assert(hasSerdeIgnoreCase(E.d));
enum serdeScoped;
Can be applied only to strings fields. Does not allocate new data when deserializeing. Raw data is used for strings instead of new memory allocation. Use this attributes only for strings or arrays that would not be used after deallocation.
enum serdeRequired;
Attribute that force deserializer to throw an exception that the field hasn't been not found in the input.
enum serdeOptional;
Attribute that allow deserializer to do not throw an exception if the field hasn't been not found in the input.
enum serdeAllowMultiple;
Attribute that allow deserializer to don't throw an exception that the field matches multiple keys in the object.
struct serdeTransformIn(alias fun);
Attributes for in transformation. Return type of in transformation must be implicitly convertable to the type of the field. In transformation would be applied after serialization proxy if any.
template serdeGetTransformIn(alias value)
Returns:
unary function of underlaying alias of serdeTransformIn
struct serdeTransformOut(alias fun);
Attributes for out transformation. Return type of out transformation may be differ from the type of the field. Out transformation would be applied before serialization proxy if any.
template serdeGetTransformOut(alias value)
Returns:
unary function of underlaying alias of serdeTransformOut
pure nothrow @nogc @safe bool serdeParseEnum(E)(const char[] str, ref E res);
Examples:
enum E
{
    @serdeKeys("A", "alpha")
    a,
    @serdeKeys("B", "beta")
    b,
    c,
}

auto e = E.c;
assert(serdeParseEnum("A", e));
assert(e == E.a);
assert(serdeParseEnum("alpha", e));
assert(e == E.a);
assert(serdeParseEnum("beta", e));
assert(e == E.b);
assert(serdeParseEnum("B", e));
assert(e == E.b);
assert(serdeParseEnum("c", e));
assert(e == E.c);

assert(!serdeParseEnum("C", e));
assert(!serdeParseEnum("Alpha", e));
Examples:
Case insensitive
@serdeIgnoreCase // supported for the whole type
enum E
{
    @serdeKeys("A", "alpha")
    a,
    @serdeKeys("B", "beta")
    b,
    c,
}

auto e = E.c;
assert(serdeParseEnum("a", e));
assert(e == E.a);
assert(serdeParseEnum("alpha", e));
assert(e == E.a);
assert(serdeParseEnum("BETA", e));
assert(e == E.b);
assert(serdeParseEnum("b", e));
assert(e == E.b);
assert(serdeParseEnum("C", e));
assert(e == E.c);
template serdeDeserializationMemberType(T, string member)

template serdeDeserializationMemberType(T)
Deserialization member type
template serdeIsDeserializable(T)
Is deserializable member
Examples:
static struct S
{
    @serdeIgnore
    int i;

    @serdeKeys("a", "b")
    int a;
}

alias serdeIsDeserializableInS = serdeIsDeserializable!S;
static assert (!serdeIsDeserializableInS!"i");
static assert (serdeIsDeserializableInS!"a");
enum bool serdeIsDeserializable(string member);
template serdeSerializationMemberType(T, string member)

template serdeSerializationMemberType(T)
Serialization member type
template serdeIsSerializable(T)
Is deserializable member
Examples:
static struct S
{
    @serdeIgnore
    int i;

    @serdeKeys("a", "b")
    int a;
}

alias serdeIsSerializableInS = serdeIsSerializable!S;
static assert (!serdeIsSerializableInS!"i");
static assert (serdeIsSerializableInS!"a");
enum bool serdeIsSerializable(string member);
template serdeGetFinalProxy(T)
Final proxy type
Examples:
@serdeProxy!string
static struct A {}

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}

static assert (is(serdeGetFinalProxy!C == string), serdeGetFinalProxy!C.stringof);
static assert (is(serdeGetFinalProxy!string == string));
template serdeGetFinalDeepProxy(T)
Final deep proxy type
Examples:
@serdeProxy!string
static struct A {}

enum E {a,b,c}

@serdeProxy!(A[E])
static struct B {}

@serdeProxy!(B[])
static struct C {}

static assert (is(serdeGetFinalDeepProxy!C == A[E]));
static assert (is(serdeGetFinalDeepProxy!string == string));
template serdeFinalProxyDeserializableMembers(T)
Final proxy type deserializable members
Examples:
static struct A
{
    @serdeIgnore
    int i;

    @serdeKeys("a", "b")
    int m;
}

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}

static assert (serdeFinalProxyDeserializableMembers!C == ["m"]);
template serdeFinalDeepProxySerializableMembers(T)
Final deep proxy type serializable members
Examples:
static struct A
{
    @serdeIgnore
    int i;

    @serdeKeys("a", "b")
    int m;
}

@serdeProxy!(A[string])
static struct B {}

@serdeProxy!(B[])
static struct C {}

static assert (serdeFinalDeepProxySerializableMembers!C == ["m"]);
template serdeFinalProxySerializableMembers(T)
Final proxy type deserializable members
Examples:
static struct A
{
    @serdeIgnore
    int i;

    @serdeKeys("a", "b")
    int m;
}

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}

static assert (serdeFinalProxySerializableMembers!C == ["m"]);
template serdeFinalDeepProxyDeserializableMembers(T)
Final deep proxy type serializable members
Examples:
static struct A
{
    @serdeIgnore
    int i;

    @serdeKeys("a", "b")
    int m;
}

@serdeProxy!(A[string])
static struct B {}

@serdeProxy!(B[])
static struct C {}

static assert (serdeFinalDeepProxyDeserializableMembers!C == ["m"]);
template serdeFinalDeserializationMemberType(T, string member)

template serdeFinalDeserializationMemberType(T)
Deserialization member final proxy type
Examples:
static struct A
{
    
}

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}


@serdeProxy!double
struct E {}

struct D
{
    C c;

    @serdeProxy!E
    int d;
}

static assert (is(serdeFinalDeserializationMemberType!(D, "c") == A));
static assert (is(serdeFinalDeserializationMemberType!(D, "d") == double));
template serdeDeserializationFinalProxyMemberTypes(T)
Deserialization members final proxy types
Examples:
static struct A {}

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}

@serdeProxy!B
static struct E {}

static struct D
{
    C c;

    @serdeProxy!E
    int d;
}

import std.meta: AliasSeq;
static assert (is(serdeDeserializationFinalProxyMemberTypes!D == AliasSeq!A));
template serdeFinalSerializationMemberType(T, string member)

template serdeFinalSerializationMemberType(T)
Serialization member final proxy type
Examples:
static struct A
{
    
}

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}


@serdeProxy!double
struct E {}

struct D
{
    C c;

    @serdeProxy!E
    int d;
}

static assert (is(serdeFinalSerializationMemberType!(D, "c") == A), serdeFinalSerializationMemberType!(D, "c"));
static assert (is(serdeFinalSerializationMemberType!(D, "d") == double));
template serdeSerializationFinalProxyMemberTypes(T)
Serialization members final proxy types
Examples:
static struct A {}

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}

@serdeProxy!B
static struct E {}

static struct D
{
    C c;

    @serdeProxy!E
    int d;
}

import std.meta: AliasSeq;
static assert (is(serdeSerializationFinalProxyMemberTypes!D == AliasSeq!A));
template serdeDeserializationFinalDeepProxyMemberTypes(T)
Deserialization members final deep proxy types
Examples:
static struct A {}

@serdeProxy!(A[])
static struct B {}

enum R {a, b, c}

@serdeProxy!(B[R])
static struct C {}

@serdeProxy!(B[string])
static struct E {}

static struct D
{
    C c;

    @serdeProxy!E
    int d;
}

import std.meta: AliasSeq;
static assert (is(serdeDeserializationFinalDeepProxyMemberTypes!D == AliasSeq!A), serdeDeserializationFinalDeepProxyMemberTypes!D);
template serdeSerializationFinalDeepProxyMemberTypes(T)
Serialization members final deep proxy types
Examples:
static struct A {}

@serdeProxy!(A[])
static struct B {}

enum R {a, b, c}

@serdeProxy!(B[R])
static struct C {}

@serdeProxy!(B[string])
static struct E {}

static struct D
{
    C c;

    @serdeProxy!E
    int d;
}

import std.meta: AliasSeq;
static assert (is(serdeSerializationFinalDeepProxyMemberTypes!D == AliasSeq!A), serdeSerializationFinalDeepProxyMemberTypes!D);
template serdeDeserializationFinalProxyMemberTypesRecurse(T)
Deserialization members final proxy types (recursive)
Examples:
static struct A { double g; }

@serdeProxy!A
static struct B {}

@serdeProxy!B
static struct C {}

@serdeProxy!B
static struct E {}

static struct D
{
    C c;

    @serdeProxy!E
    int d;
}

@serdeProxy!D
static struct F {}

import std.meta: AliasSeq;
static assert (is(serdeDeserializationFinalProxyMemberTypesRecurse!F == AliasSeq!(D, A, double)));
template serdeDeserializationFinalDeepProxyMemberTypesRecurse(T)
Deserialization members final deep proxy types (recursive)
Examples:
static struct A { double g; }

@serdeProxy!(A[])
static struct B {}

@serdeProxy!(B[string])
static struct C {}

@serdeProxy!B
static struct E {}

static struct D
{
    C c;

    @serdeProxy!(E[])
    int d;
}

@serdeProxy!D
static struct F {}

import std.meta: AliasSeq;
static assert (is(serdeDeserializationFinalDeepProxyMemberTypesRecurse!F == AliasSeq!(D, A, double)));
template serdeSerializationFinalDeepProxyMemberTypesRecurse(T)
Serialization members final deep proxy types (recursive)
Examples:
static struct A { double g; }

@serdeProxy!(A[])
static struct B {}

@serdeProxy!(B[string])
static struct C {}

@serdeProxy!B
static struct E {}

static struct D
{
    C c;

    @serdeProxy!(E[])
    int d;
}

@serdeProxy!D
static struct F {}

import std.meta: AliasSeq;
static assert (is(serdeSerializationFinalDeepProxyMemberTypesRecurse!F == AliasSeq!(D, A, double)), serdeSerializationFinalDeepProxyMemberTypesRecurse!F);
enum string[] serdeGetSerializationKeysRecurse(T);
Serialization members final proxy keys (recursive)
Examples:
enum Y
{
    a,
    b,
    c,
}

static struct A { double g; float d; }

@serdeProxy!A
static struct B {  int f; }

@serdeProxy!(B[Y][string])
static union C {  int f; }

@serdeProxy!(B[])
static interface E {  int f() @property; }

enum N { a, b }

static class D
{
    C c;

    @serdeProxy!(E[])
    int d;

    N e;
}

@serdeAlgebraicAnnotation("$F")
@serdeProxy!D
static struct F { int f; }

static assert (serdeGetSerializationKeysRecurse!F == ["a", "b", "c", "d", "e", "g"]);

import mir.algebraic;
static assert (serdeGetSerializationKeysRecurse!(Nullable!(F, int)) == ["a", "b", "c", "d", "e", "g", "$F"]);
enum string[] serdeGetDeserializationKeysRecurse(T);
Deserialization members final proxy keys (recursive)
Examples:
static struct A { double g; float d; }

@serdeProxy!A
static struct B {  int f; }

@serdeProxy!(B[string])
static union C {  int f; }

@serdeProxy!(B[])
static interface E {  int f() @property; }

enum N { a, b }

static class D
{
    C c;

    @serdeProxy!(E[])
    int d;

    N e;
}

@serdeAlgebraicAnnotation("$F")
@serdeProxy!D
static struct F { int f; }

static assert (serdeGetDeserializationKeysRecurse!N == ["a", "b"], serdeGetDeserializationKeysRecurse!N);

static assert (serdeGetDeserializationKeysRecurse!F == ["a", "b", "c", "d", "e", "g"]);

import mir.algebraic;
static assert (serdeGetDeserializationKeysRecurse!(Nullable!(F, int)) == ["a", "b", "c", "d", "e", "g", "$F"]);
enum serdeOrderedIn;
UDA used to force deserializer to initilize members in the order of their definition in the target object/structure.
The attribute force deserializer to create a dummy type (recursively), initializer its fields and then assign them to to the object members (fields and setters) in the order of their definition.
enum serdeRealOrderedIn;
UDA used to force deserializer to initilize members in the order of their definition in the target object/structure.
Unlike serdeOrderedIn serdeRealOrderedDummy force deserialzier to iterate all DOM keys for each object deserialization member. It is slower but more universal approach.
enum serdeFromDummyByUser;
UDA used to force deserializer to skip the member final deserialization. A user should finalize the member deserialize using the dummy object provided in serdeFinalizeWithDummy(ref SerdeOrderedDummy!(typeof(this)) dummy) struct method and dummy method serdeFinalizeTargetMember.
enum serdeAlphabetOut;
UDA used to force serializer to output members in the alphabetical order of their output keys.
struct SerdeOrderedDummy(T, bool __optionalByDefault = false) if (is(serdeGetFinalProxy!T == T) && isAggregateType!T);
A dummy structure usefull serdeOrderedIn support.
Examples:
import std.traits;

static struct S
{
    private double _d;

    @serdeProxy!int
    void d(double v) @property { _d = v; }

    string s;
}

static assert(is(typeof(SerdeOrderedDummy!S.init.d) == double), SerdeOrderedDummy!S.init.d);
static assert(is(typeof(SerdeOrderedDummy!S.init.s) == string));
static assert(hasUDA!(S.d, serdeProxy));
static assert(hasUDA!(SerdeOrderedDummy!S.d, serdeProxy));
void serdeFinalizeWithFlags(ref scope const SerdeFlags!(typeof(this)) flags);
Initialize target members
void serdeFinalizeTarget(ref T value, ref scope SerdeFlags!T flags);
Initialize target members
void serdeFinalizeTargetMember(string member)(ref T value);
Initialize target member
struct SerdeFlags(T);
A dummy structure passed to .serdeFinalizeWithFlags finalizer method.