Libmir Archive

Serialization in D — JSON, MessagePack, CBOR & ION with mir-ion

Serialize and deserialize D structs to JSON, MessagePack, and Amazon ION with mir-ion — one set of attributes, many formats. Compiled against current Mir source.

How to serialize D data with mir-ion. One key idea: you annotate your types once with mir.serde attributes, then serialize to any supported format — JSON, MessagePack, CBOR, YAML, or Amazon ION binary. For the full API, browse mir-ion.libmir.org.

Every example compiles against current mir-ion. Serialize/deserialize functions return/accept plain values — codecs are generated at compile time from your struct definition, so there's no runtime reflection cost.

JSON round-trip

import mir.ser.json: serializeJson;
import mir.deser.json: deserializeJson;

struct Point { double x; double y; string label; }

auto p = Point(1.5, 2.5, "origin");
string j = p.serializeJson;            // {"x":1.5,"y":2.5,"label":"origin"}
auto back = j.deserializeJson!Point;   // round-trip back to a Point
assert(back == p);

serializeJson produces a string; deserializeJson!T parses straight into your type T.

One type, many formats

import mir.ser.msgpack: serializeMsgpack;
import mir.deser.msgpack: deserializeMsgpack;
import mir.ser.ion: serializeIon;
import mir.deser.ion: deserializeIon;

struct Config { string host; int port; bool tls; }

auto c = Config("localhost", 8080, true);
auto mp  = c.serializeMsgpack;          // MessagePack bytes (immutable(ubyte)[])
auto ion = c.serializeIon;              // Amazon ION binary
auto c2 = mp.deserializeMsgpack!Config;
auto c3 = ion.deserializeIon!Config;
assert(c2 == c && c3 == c);

The binary serializers return immutable(ubyte)[]. The same struct serializes to JSON, MessagePack, CBOR, YAML, and ION with no per-format code.

Customising field mapping

import mir.serde: serdeKeys, serdeOptional, serdeIgnore;

struct User {
    @serdeKeys("user_name") string name;   // rename on the wire
    int age;
    @serdeOptional bool admin;             // may be absent when reading
    @serdeIgnore string cachedToken;       // never serialized
}

mir.serde attributes control the wire format independently of your D field names — @serdeKeys renames, @serdeOptional tolerates missing fields, @serdeIgnore skips a field entirely. See mir.serde for the full set.

Where to go next

On this page