joetjen.net
EN DE
Data format

The DXN data format

DXN — Data eXchange Notation — is one data model written two ways: .dxn, a text form you can read and edit, and .dxnb, a binary form built on CBOR. Both carry the same 28 types, from exact decimals to sets, structs and timestamps, and convert into each other without loss.

Format 1.0

A first look

A DXN document is a single value. This one is a map that uses most of the format at once:

user.dxn
@dxn "1.0"
%{
  id:      @uuid "550e8400-e29b-41d4-a716-446655440000"
  name:    "Ada Lovelace"
  active:  true
  score:   19.99M
  tags:    @{:admin :staff}
  meta:    @ordered %{created: ~U[1990-01-01 00:00:00Z]}
  address: %Point[51.05, 13.74]
  result:  {:ok, 200}
  handle:  ~r/^[a-z0-9_]{3,20}$/i
}
  • @dxn "1.0" is an optional header naming the format version.
  • %{…} is a map; name: is a keyword key. Commas are optional everywhere.
  • 19.99M is an exact decimal, not a float — the type for money.
  • @{…} is a set, {…} a tuple, @ordered %{…} a map whose order is part of its value.
  • %Point[…] is a struct, written by position; a schema gives its fields names and types.
  • @uuid, ~U[…] and ~r/…/ are a UUID, a UTC timestamp and a regular expression — values of their own types, not strings.

The same document as .dxnb takes 215 bytes instead of 305, and decodes back to exactly the same value.

Design

  • One model, two encodings. Every value has a text form and a binary form, and the round trip between them is lossless.
  • Exact numbers. Integers have arbitrary precision; decimals and rationals are exact and stay that way in binary.
  • Intent in the syntax. A tuple is not a list, an ordered map is not a map, a set is not a list without duplicates — the difference is written down, not agreed on the side.
  • Graceful degradation. A struct or tag a reader knows nothing about still parses, into an opaque value it can pass on unchanged.
  • Schemas in the same notation. A .dxns schema is a DXN document; there is no second language to learn.
  • Familiar to Elixir eyes. Maps, tuples, keywords, sigils and ?c characters are written the way Elixir writes them.

File facts

PropertyValue
Extensions.dxn text, .dxnb binary, .dxns schema
Text encodingUTF-8
Text header@dxn "1.0" — optional, first form only
BinaryDX, a version byte, then one CBOR item (RFC 8949) — see Binary format
Comments# to the end of the line; text only
GrammarPEG, written in Aether — see Grammar

Implementations

These pages describe the format. The libraries below read and write it; each documents its own API.

NameLanguageRole
dextrinElixirThe reference implementation: text, binary and schemas
node-dextrinJavaScriptThe same documents for Node.js
php-dextrinPHPThe same documents for PHP
dextrin_htmlElixirConverts between HTML and DXN
ichorElixirThe grammar compiler that generates dextrin’s text parser

On these pages

  • Text format — documents, separators, comments, identifiers, tags and discard.
  • Values — all 28 types and how to write them.
  • Binary format — the envelope, the CBOR mapping, private tags and value sharing.
  • Schemas — .dxns documents: type expressions, struct schemas and enforcement.
  • Grammar — the formal grammar and where the reference implementation still differs from it.