A real-life example
One schema, one Document, validated against an order written in OML (Omnist's own format -- see the guide). The same Document also reads in from JSON, YAML, TOML, and XML.
For worked examples using real external formats rather than one designed for Omnist, see the examples/ directory (pyproject.toml, package.json, a GitHub Actions workflow, sitemap.xml).
The schema
An order: an id, a status, a total, a shipping address, one or more line items, and an optional coupon. The whole thing sits under a single top-level order key -- that makes it single-rooted, so the same Document comes back from JSON, YAML, TOML, and XML (XML always has one document element).
record Address { "street": string, "city": string }
record LineItem { "sku": string, "qty": integer, "price": number }
record Order {
"id": string,
"status": string,
"total": number,
"address": Address,
"items" [1,]: LineItem, # at least one line item
"coupon" [0,1]: string, # optional
}
record Root { "order": Order } # single top-level key
root Rootgraph LR
Root["Root"] -->|"order [1,1]"| Order["Order"]
Order -->|"address [1,1]"| Address["Address"]
Order -->|"items [1,]"| LineItem["LineItem"]The same schema with the builder functions:
import { schema, record, field, ref, t } from "@omnist-dev/omnist";
const address = record(field("street", t.string), field("city", t.string));
const lineItem = record(
field("sku", t.string), field("qty", t.integer), field("price", t.number),
);
const order = record(
field("id", t.string),
field("status", t.string),
field("total", t.number),
field("address", ref("Address")),
field("items", ref("LineItem"), 1, null), // [1,]
field("coupon", t.string, 0, 1), // optional
);
const s = schema(ref("Root"), {
Root: record(field("order", ref("Order"))),
Order: order, Address: address, LineItem: lineItem,
});The order, in OML
import { parseSchema, readOml, Doc } from "@omnist-dev/omnist";
const s = parseSchema(SCHEMA); // the OSD above
const node = readOml(`
order: {
id: "A1"
status: "shipped"
total: 42.50
address: {
street: "1 Main St"
city: "Springfield"
}
items: {
sku: "WIDGET-1"
qty: 2
price: 15.00
}
items: {
sku: "GADGET-2"
qty: 1
price: 12.50
}
}
`);
const d = new Doc(node);
s.validate(d).ok; // trueNote OML objects separate fields by newlines (or ;), not commas -- a comma is only used inside [...] array sugar. See the OML format page for the full grammar.
Translating to other formats
The same Document, once built, can be written to (or read from) any registered format with read*/write*: readJson/writeJson, readYaml/writeYaml, readToml/writeToml, readXml/writeXml. Each format's own page documents what, if anything, it adjusts on the way in or out -- see Formats.