$defs a $ref
Do $defs ulož pojmenovaná schémata. Odkaz $ref je aplikuje na stejnou hodnotu, kterou právě validuješ. Lokální fragment #/$defs/zakaznik adresuje schéma uvnitř tohoto dokumentu, nikoli vlastnost v datech.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"zakaznik": {
"type": "object",
"properties": {
"jmeno": {
"type": "string"
}
},
"required": [
"jmeno"
]
}
},
"allOf": [
{
"$ref": "#/$defs/zakaznik"
}
],
"properties": {
"aktivni": {
"type": "boolean"
}
},
"required": [
"aktivni"
],
"unevaluatedProperties": false
} V 2020-12 se vyhodnocují i další klíčová slova vedle $ref. V Draft 7 byla vedle odkazu ignorována. Vnořené $id mění základ URI a hranici zdroje schématu; při přemísťování definic proto kontroluj odkazy.
Logické kombinace
| Slovo | Podmínka |
|---|---|
| allOf | musí vyhovět každému schématu |
| anyOf | musí vyhovět alespoň jednomu |
| oneOf | musí vyhovět právě jednomu |
| not | nesmí vyhovět zadanému schématu |
allOf nepřepisuje ani neslučuje definice jako dědičnost v programovacím jazyce. Všechny podmínky musí platit současně. Kombinace type: string a type: number přes allOf nepřijme žádnou hodnotu.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"oneOf": [
{
"type": "object",
"properties": {
"druh": {
"const": "osoba"
},
"jmeno": {
"type": "string"
}
},
"required": [
"druh",
"jmeno"
]
},
{
"type": "object",
"properties": {
"druh": {
"const": "firma"
},
"ico": {
"type": "string",
"pattern": "^[0-9]{8}$"
}
},
"required": [
"druh",
"ico"
]
}
],
"unevaluatedProperties": false
} Rozlišovací vlastnost druh zajišťuje, že větve nemohou uspět zároveň. Bez ní může například číslo vyhovět větvi number i integer, a oneOf ho odmítne. Pokud chceš překryv dovolit, použij anyOf.
Proč additionalProperties nestačí při rozšiřování
additionalProperties vidí deklarace ve svém dílčím schématu. Pokud uzavřeš základ zákazníka, odmítne aktivni i tehdy, když ho jiná větev allOf povoluje. Uzavři až výsledek pomocí unevaluatedProperties: false, jako v prvním příkladu. To vyžaduje dialekt 2019-09 nebo novější a podporu validátoru.
Úspěšně vyhodnocené vlastnosti se sbírají podle pravidel aplikátorů. Neznamená to, že jakákoli zmínka o názvu v neúspěšné větvi automaticky dovolí vlastnost.
Externí odkazy a doporučené postupy
$ref může odkazovat také na jiný zdroj. Aplikace má schémata registrovat pod očekávanými URI a určit, které zdroje smí načíst. Online nástroj XML.cz externí schémata automaticky nestahuje; pro ukázky používej lokální $defs.
- Ve znovu použitelných dílčích schématech ponech další pole povolená. Zakaž je až ve výsledném schématu konkrétního vstupu.
- Každou alternativu otestuj platnými i chybnými daty.
- Omez hloubku a velikost dat a složitost schémat, zejména u rekurze.
- Změnu dialektu ber jako migraci a ověř ji podle přehledu verzí.
oneOf a anyOf: proč celé číslo může selhat
Hodnota 1.5 projde pouze number a je platná. Hodnota 1 projde number i integer a oneOf ji odmítne. Po změně na anyOf projdou obě. oneOf počítá úspěšné větve, nevybírá automaticky „nejlepší typ“. U zpráv používej rozlišovací vlastnost s const a required v každé větvi.
Lokální rekurzivní schéma
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"uzel": {
"type": "object",
"required": [
"nazev"
],
"properties": {
"nazev": {
"type": "string"
},
"deti": {
"type": "array",
"items": {
"$ref": "#/$defs/uzel"
}
}
},
"additionalProperties": false
}
},
"$ref": "#/$defs/uzel"
} {"nazev":"XML","deti":[{"nazev":"XPath"},{"nazev":"XSD"}]} Odkaz v items aplikuje stejný typ na každého potomka. Dítě bez nazev neprojde required. Prázdné deti je platné a vynechané deti také; přítomnost seznamu není povinná. Rekurze schématu nevytváří sama cyklická JSON data, protože JSON text cyklické odkazy neobsahuje.
Omez hloubku a počet uzlů v aplikaci. Pro rozšiřitelnou rekurzi existují dynamické odkazy, jejichž chování závisí na dialektu; lokální $ref v této ukázce má jednoduchý pevný cíl. $id je identifikátor a základ URI schématu, nikoli příkaz automaticky stahovat soubor.