Against everything else
Each row is a property a reader can verify in an afternoon. No row is a matter of taste, and no opponent is chosen for being easy — CBOR and Ion are the closest existing things and are the ones worth losing to.
The matrix
| property | json | yaml | xml | toml | cbor | ion | protobuf | rdf | unimsg |
|---|---|---|---|---|---|---|---|---|---|
| human-writable | yes | yes | poor | yes | no | yes | no | poor | yes |
| exact integers beyond 2^53 | no | no | n-a | yes | yes | yes | yes | yes | yes |
| exact decimals | no | no | n-a | no | tag | yes | no | yes | yes |
| native binary | no | no | no | no | yes | yes | yes | no | yes |
| timestamps with precision kept | no | partial | yes | yes | tag | yes | no | yes | yes |
| comments | no | yes | yes | yes | no | yes | n-a | yes | yes |
| self-describing | yes | yes | yes | yes | yes | yes | no | yes | yes |
| canonical form in the base spec | no | no | no | no | yes | no | no | no | yes |
| lossless text/binary duality | n-a | n-a | n-a | n-a | no | yes | no | no | yes |
| extensions that degrade legibly | no | no | partial | no | partial | partial | no | yes | yes |
| no evaluation at parse time | yes | no | no | yes | yes | yes | yes | yes | yes |
| content-addressed definitions | no | no | no | no | no | no | no | partial | yes |
What each column was checked against
| column | version | checked-on | against |
|---|---|---|---|
| json | RFC 8259 | unchecked | docs/01-survey.md |
| yaml | YAML 1.2.2 | unchecked | docs/01-survey.md |
| xml | XML 1.0, 5th ed. | unchecked | docs/01-survey.md |
| toml | TOML 1.0.0 | unchecked | docs/01-survey.md |
| cbor | RFC 8949 | unchecked | spec/unimsg-v0.umsg, which profiles it |
| ion | Ion 1.0 | unchecked | docs/01-survey.md |
| protobuf | proto3 | unchecked | docs/01-survey.md |
| rdf | RDF 1.1 | unchecked | docs/01-survey.md |
| unimsg | v0, provisional | this-build | spec/unimsg-v0.umsg, parsed by this build |
Lossless duality and degradable extensions. Everything else in that table is available somewhere already, and a format offering only the rest would not be worth writing.
The reasoning under each column
From the survey, unedited. A column in that table is a summary of a paragraph someone wrote after reading the format's specification; the paragraph is the part worth arguing with.
json
The reigning champion by accident.
- No integer type. Numbers are IEEE-754 doubles in practice;
2^53 + 1silently
corrupts. Fatal for identifiers, ledgers, and scientific data.
- No binary. Base64 costs 33% and obscures intent.
- No date/time type. Every application invents one.
- No NaN or Infinity. Round-tripping numeric computation is lossy.
- No comments. The single biggest social failure; it is why every JSON-based
config format eventually gets replaced.
- Duplicate keys undefined. Real interoperability hazard.
- No cycles or shared references. Graphs must be hand-encoded.
- No streaming framing, no chunking, no random access.
- No extension mechanism at all. Every extension is a naming convention
({"$type": …}) and every such convention collides with someone else's.
The last point is the decisive one. JSON is not extensible; it is merely permissive.
yaml
JSON plus ergonomics plus footguns.
- Anchors and aliases give genuine DAGs and cycles — a real advantage nobody credits.
- Indentation encodes shape, which is why it reads well.
- The specification is enormous and implementations diverge; YAML 1.1 vs 1.2 is still
unsettled in the wild.
- Value-dependent coercion:
NOparses asfalse(the "Norway problem"). Any
coercion rule that depends on the *value* rather than the *lexical form* is a defect.
yaml.loadwas a remote-code-execution primitive in Python for a decade.
Better than JSON for humans, worse for machines, not a candidate for a wire format.
xml
Genuinely good at *documents*, genuinely bad at *data*.
- Mixed content, attributes, and namespaces are real strengths for prose-like data
and are underappreciated.
- Everything is a string until XSD bolts types on.
- Attribute-vs-element is a permanent, unresolvable modelling coin-flip.
- Whitespace handling is ambiguous.
- Closing tags roughly double glyph count without adding information — the
signal-to-noise ratio is visible from across the room, and this is why it lost
socially.
- Security legacy: XXE, billion-laughs entity expansion. Both are consequences of
resolving and expanding things at parse time, a mistake this project treats as
categorically prohibited (see 04).
toml
Config-scale formats. TOML's nesting story degrades badly beyond two levels. None
target universality and none should be judged against it. KDL is worth studying purely
for syntax ergonomics.
cbor
The two closest existing things to unimsg. Treated in detail in
07-foundation-cbor-ion.
Briefly: CBOR (RFC 8949) has a small typed kernel, native binary, an IANA tag registry,
a deterministic encoding profile, a schema language (CDDL, RFC 8610), a signing layer
(COSE), a content-addressed dialect (DAG-CBOR), and very broad deployment — WebAuthn /
FIDO2, the EU digital COVID certificates, and Bluesky's repository format. Ion has
arbitrary-precision decimals, proper timestamps, stackable annotations, symbol tables,
s-expressions, and a lossless text/binary duality.
Between them, roughly 80% of unimsg already exists.
ion
The two closest existing things to unimsg. Treated in detail in
07-foundation-cbor-ion.
Briefly: CBOR (RFC 8949) has a small typed kernel, native binary, an IANA tag registry,
a deterministic encoding profile, a schema language (CDDL, RFC 8610), a signing layer
(COSE), a content-addressed dialect (DAG-CBOR), and very broad deployment — WebAuthn /
FIDO2, the EU digital COVID certificates, and Bluesky's repository format. Ion has
arbitrary-precision decimals, proper timestamps, stackable annotations, symbol tables,
s-expressions, and a lossless text/binary duality.
Between them, roughly 80% of unimsg already exists.
protobuf
Fast, compact, and not self-describing. Bytes are meaningless without the schema,
which makes them transports rather than storage formats.
- Protobuf field numbers are a durable but fragile coordination mechanism.
- Protobuf 3 spent years discarding unknown fields, silently breaking forward
compatibility for anything in the middle of a pipeline. This is the strongest
available evidence that **unknown-preserving round-trip must be a conformance
requirement**, not a nicety.
- Avro's schema-resolution rules are the best thought-out evolution story in this
family and are worth studying.
rdf
- RDF provides global identity via IRIs and a genuine graph model. The ecosystem is
heavy and RDF/XML is a canonical example of expressive-but-unreadable.
- IPLD / DAG-CBOR is the most relevant: content-addressed Merkle DAGs, meaning a
document can reference data larger than itself, verifiably. This capability is
adopted directly in these designs.
unimsgnot in the survey
The survey does not discuss this format on its own. The column stands on the rows alone.
Three of them are not rivals in the same way
on cbor
unimsg is CBOR. The kernel is RFC 8949's, the canonical encoding is a deterministic profile of it, and a unimsg document decodes in any CBOR library on earth. What is added is a text syntax that projects it losslessly, and a discipline for extensions. Presenting CBOR as a rival misstates the relationship: it is the foundation, and the site says so on the comparison page rather than in a footnote.
on ion
Amazon Ion had the text/binary duality first, and had it properly. The differences are the degradable-extension rule and the content-addressed definitions, plus a much smaller surface. Ion's decimals and timestamps are better than most of what follows them.
on json
JSON is not extensible; it is permissive. Every extension it has is a naming convention, and every naming convention collides with someone else's. That is the sentence the comparison page is built around.
Where it loses
In the same table, same size, not in a collapsed section. A comparison page that only wins is read as advertising and discarded whole, including the true parts.
| against | loses-on |
|---|---|
| JSON | ubiquity, and it is not close. Every language parses JSON in its standard library and none parses unimsg. |
| Protobuf | size and speed on a known schema, permanently. Self-description costs bytes and always will. |
| Parquet | anything at scale. unimsg has no columnar story and no random access into a large value. |
| YAML | familiarity in configuration, where its footguns rarely fire and its ergonomics are known. |
| XML | mixed content. Prose with markup inside it remains XML's, and this document does not pretend otherwise. |
What this site is not doing
a package registry, a *hosted* validator, or accounts of any kind. The emphasis matters and was missing until a reader asked why a format's site would refuse to tell anyone whether their document is valid. It does not refuse: the playground parses, encodes and round-trips in the reader's own browser, which is validation, and
/docreports the same. What is ruled out is a validator *we run* — an endpoint, a queue, an abuse surface, and a service to keep alive, none of which a static site has and all of which it would need. A checker that runs on the reader's machine costs a download; one that runs on ours costs forever.a comparison that flatters unimsg by choosing weak opponents — CBOR and Ion are the closest things to it and are treated as the serious rivals they are
claiming adoption. There is none, and a site that implies otherwise is lying about the only fact a reader can check in ten seconds