Why Omnist
The problem this exists to solve, and what it makes possible.
JSON, YAML, TOML, and XML all encode the same kind of tree-shaped data — but each ships its own parser, its own types, and its own edge cases. There's no shared model underneath, so converting between them, validating one against a shared shape, or safely evolving that shape over time all end up hand-rolled and unchecked.
Omnist exists to close three gaps specifically:
- One model, many formats. Read JSON, YAML, TOML, XML, or Omnist's own OML into the same tree, validate it against one schema, write it back out to any of the others — a genuine read one, write another, not a lossy best-effort conversion.
- Schema evolution you can prove, not guess at. "Will every document written under the old schema still validate under the new one?" is a question
compatible_withanswers with a proven yes or no — the kind of check a CI gate runs before a schema change merges, not something a reviewer eyeballs. - A schema algebra, not just a schema. Trimming a schema down to what one service actually uses, or drafting one from real examples instead of writing it by hand, are both single decidable operations —
extractandinfer— not scripts you'd have to write yourself.
The reason all of this is decidable — provably correct, not a heuristic that mostly works — is a deliberate constraint: records are closed by default, and scalar types are never composed into enums or unions. The one deliberate opening is an explicitly marked any. That discipline is what the rest of this tutorial actually demonstrates, one operation at a time.
This tutorial uses Python — one of five independent language ports, all built against the same specification. Everything from here on exists the same way in the other four; only the surface syntax changes.