// Copyright 2026 Leo Cheng
// SPDX-License-Identifier: Apache-2.0
// One document, six readings: the places where the versions actually differ.
// Run it with `moon run examples/versions`.
///|
fn main raise {
// `exclusiveMaximum` was a boolean beside `maximum` through draft-04, and a
// number of its own from draft-06. A document holding the flag means "ten is
// out of bounds" at draft-04, and at every later version the flag is not a
// number, asserts nothing, and ten is allowed.
let flag = @json.parse("{ \"maximum\": 10, \"exclusiveMaximum\": true }")
println("maximum 10, exclusiveMaximum true — is ten allowed?")
for
draft in [
@moonschema.Draft::Draft4,
Draft6,
Draft7,
Draft2019,
Draft2020,
V1,
] {
let schema = @moonschema.Schema::new(flag, draft~)
println(" \{draft} \{schema.valid(Json::number(10.0))}")
}
// A list of schemas for the leading items was `items` before 2020-12, and is
// `prefixItems` after it. Read at the other version the keyword is not one
// that version has, so it asserts nothing — and the item goes unchecked.
// This is why a document should say which version wrote it.
let spellings = [
("items ", "{\"items\": [{\"type\": \"string\"}]}"),
("prefixItems", "{\"prefixItems\": [{\"type\": \"string\"}]}"),
]
println("\nthe first item should be a string; here it is 2:")
for pair in spellings {
let (label, text) = pair
for draft in [@moonschema.Draft::Draft2019, Draft2020] {
let schema = @moonschema.Schema::new(@json.parse(text), draft~)
println(
" \{label} at \{draft}: [2] is \{schema.valid(@json.parse("[2]"))}",
)
}
}
// `dependencies` was split in 2019-09 into `dependentRequired` for the names
// and `dependentSchemas` for the schemas. A document that writes the new pair
// is a document from 2019-09 or later; at draft-07 both names are unknown.
let needs = @json.parse("{ \"dependentRequired\": { \"a\": [\"b\"] } }")
println("\ndependentRequired — a needs b — for the instance {\"a\": 1}:")
for draft in [@moonschema.Draft::Draft7, Draft2019, Draft2020] {
let schema = @moonschema.Schema::new(needs, draft~)
println(" \{draft} \{schema.valid(@json.parse("{\"a\": 1}"))}")
}
// `propertyDependencies` arrived in v1: one property's value chooses the
// subschema the whole instance is then validated against. Before v1 the
// keyword is unknown, and an unknown keyword asserts nothing.
let chosen = @json.parse(
(
#|{ "propertyDependencies": {
#| "kind": { "card": { "required": ["number"] } } } }
),
)
println("\npropertyDependencies — a card needs a number:")
for draft in [@moonschema.Draft::Draft2020, V1] {
let schema = @moonschema.Schema::new(chosen, draft~)
println(" \{draft} \{schema.valid(@json.parse("{\"kind\": \"card\"}"))}")
}
// A document that names a version is read at the version it names, whatever
// the `draft` argument says: the document is the more specific of the two.
let named = @json.parse(
(
#|{ "$schema": "http://json-schema.org/draft-04/schema#",
#| "maximum": 10, "exclusiveMaximum": true }
),
)
let strict = @moonschema.Schema::new(
named,
draft=@moonschema.Draft::Draft2020,
)
println(
"\nnamed draft-04, asked for 2020-12 — ten is \{strict.valid(Json::number(10.0))}",
)
}