writing-json-schemas

安装量: 46
排名: #16065

安装

npx skills add https://github.com/zaggino/z-schema --skill writing-json-schemas
Writing JSON Schemas for z-schema
Write correct, idiomatic JSON Schemas validated by z-schema. Default target:
draft-2020-12
.
Schema template
Start every schema with a
$schema
declaration and
type
:
{
"$schema"
:
"https://json-schema.org/draft/2020-12/schema"
,
"type"
:
"object"
,
"properties"
:
{
}
,
"required"
:
[
]
,
"additionalProperties"
:
false
}
Set
additionalProperties: false
explicitly when extra properties should be rejected — z-schema allows them by default.
Object schemas
Basic object with required fields
{
"type"
:
"object"
,
"properties"
:
{
"name"
:
{
"type"
:
"string"
,
"minLength"
:
1
}
,
"email"
:
{
"type"
:
"string"
,
"format"
:
"email"
}
,
"age"
:
{
"type"
:
"integer"
,
"minimum"
:
0
,
"maximum"
:
150
}
}
,
"required"
:
[
"name"
,
"email"
]
,
"additionalProperties"
:
false
}
Nested objects
{
"type"
:
"object"
,
"properties"
:
{
"address"
:
{
"type"
:
"object"
,
"properties"
:
{
"street"
:
{
"type"
:
"string"
}
,
"city"
:
{
"type"
:
"string"
}
,
"zip"
:
{
"type"
:
"string"
,
"pattern"
:
"^\d{5}(-\d{4})?$"
}
}
,
"required"
:
[
"street"
,
"city"
]
}
}
}
Dynamic property names
Use
patternProperties
to validate property keys by regex:
{
"type"
:
"object"
,
"patternProperties"
:
{
"^x-"
:
{
"type"
:
"string"
}
}
,
"additionalProperties"
:
false
}
Use
propertyNames
(draft-06+) to constrain all property key strings:
{
"type"
:
"object"
,
"propertyNames"
:
{
"pattern"
:
"^[a-z_]+$"
}
}
Array schemas
Uniform array
{
"type"
:
"array"
,
"items"
:
{
"type"
:
"string"
}
,
"minItems"
:
1
,
"uniqueItems"
:
true
}
Tuple validation (draft-2020-12)
Use
prefixItems
for positional types,
items
for remaining elements:
{
"type"
:
"array"
,
"prefixItems"
:
[
{
"type"
:
"string"
}
,
{
"type"
:
"integer"
}
]
,
"items"
:
false
}
items: false
rejects extra elements beyond the tuple positions.
Contains (draft-06+)
Require at least one matching item:
{
"type"
:
"array"
,
"contains"
:
{
"type"
:
"string"
,
"const"
:
"admin"
}
}
With count constraints (draft-2019-09+):
{
"type"
:
"array"
,
"contains"
:
{
"type"
:
"integer"
,
"minimum"
:
10
}
,
"minContains"
:
2
,
"maxContains"
:
5
}
String constraints
{
"type"
:
"string"
,
"minLength"
:
1
,
"maxLength"
:
255
,
"pattern"
:
"^[A-Za-z0-9_]+$"
}
Format validation
z-schema has built-in format validators:
date
,
date-time
,
time
,
email
,
idn-email
,
hostname
,
idn-hostname
,
ipv4
,
ipv6
,
uri
,
uri-reference
,
uri-template
,
iri
,
iri-reference
,
json-pointer
,
relative-json-pointer
,
regex
,
duration
,
uuid
.
{
"type"
:
"string"
,
"format"
:
"date-time"
}
Format assertions are always enforced by default (
formatAssertions: null
). For vocabulary-aware behavior in draft-2020-12, set
formatAssertions: true
on the validator.
Numeric constraints
{
"type"
:
"number"
,
"minimum"
:
0
,
"maximum"
:
100
,
"multipleOf"
:
0.01
}
Use
exclusiveMinimum
/
exclusiveMaximum
for strict bounds:
{
"type"
:
"integer"
,
"exclusiveMinimum"
:
0
,
"exclusiveMaximum"
:
100
}
Combinators
anyOf
— match at least one
{
"anyOf"
:
[
{
"type"
:
"string"
}
,
{
"type"
:
"number"
}
]
}
oneOf
— match exactly one
{
"oneOf"
:
[
{
"type"
:
"string"
,
"maxLength"
:
5
}
,
{
"type"
:
"string"
,
"minLength"
:
10
}
]
}
allOf
— match all
Use for schema composition. Combine base schemas with refinements:
{
"allOf"
:
[
{
"$ref"
:
"#/$defs/base"
}
,
{
"properties"
:
{
"extra"
:
{
"type"
:
"string"
}
}
}
]
}
not
— must not match
{
"not"
:
{
"type"
:
"null"
}
}
if
/
then
/
else
(draft-07+)
Conditional validation — prefer over complex
oneOf
when the logic is "if X then require Y":
{
"type"
:
"object"
,
"properties"
:
{
"type"
:
{
"type"
:
"string"
,
"enum"
:
[
"personal"
,
"business"
]
}
,
"company"
:
{
"type"
:
"string"
}
}
,
"if"
:
{
"properties"
:
{
"type"
:
{
"const"
:
"business"
}
}
}
,
"then"
:
{
"required"
:
[
"company"
]
}
,
"else"
:
{
}
}
When to use which combinator
Scenario
Use
Value can be multiple types
anyOf
Exactly one variant must match
oneOf
Compose inherited schemas
allOf
"if condition then require fields"
if
/
then
/
else
Exclude a specific shape
not
Prefer
if
/
then
/
else
over
oneOf
when the condition is a single discriminator field — it produces clearer error messages.
Schema reuse with
$ref
and
$defs
Local definitions
{
"$defs"
:
{
"address"
:
{
"type"
:
"object"
,
"properties"
:
{
"street"
:
{
"type"
:
"string"
}
,
"city"
:
{
"type"
:
"string"
}
}
,
"required"
:
[
"street"
,
"city"
]
}
}
,
"type"
:
"object"
,
"properties"
:
{
"home"
:
{
"$ref"
:
"#/$defs/address"
}
,
"work"
:
{
"$ref"
:
"#/$defs/address"
}
}
}
Cross-schema references
Compile an array of schemas and reference by ID:
import
ZSchema
from
'z-schema'
;
const
schemas
=
[
{
$id
:
'address'
,
type
:
'object'
,
properties
:
{
city
:
{
type
:
'string'
}
}
,
required
:
[
'city'
]
,
}
,
{
$id
:
'person'
,
type
:
'object'
,
properties
:
{
name
:
{
type
:
'string'
}
,
home
:
{
$ref
:
'address'
}
,
}
,
required
:
[
'name'
]
,
}
,
]
;
const
validator
=
ZSchema
.
create
(
)
;
validator
.
validateSchema
(
schemas
)
;
validator
.
validate
(
{
name
:
'Alice'
,
home
:
{
city
:
'Paris'
}
}
,
'person'
)
;
Strict schemas with
unevaluatedProperties
(draft-2019-09+)
When combining schemas with
allOf
,
additionalProperties: false
in a sub-schema blocks properties defined in sibling schemas. Use
unevaluatedProperties
instead — it tracks all properties evaluated across applicators:
{
"allOf"
:
[
{
"type"
:
"object"
,
"properties"
:
{
"name"
:
{
"type"
:
"string"
}
}
,
"required"
:
[
"name"
]
}
,
{
"type"
:
"object"
,
"properties"
:
{
"age"
:
{
"type"
:
"integer"
}
}
}
]
,
"unevaluatedProperties"
:
false
}
This accepts
{ "name": "Alice", "age": 30 }
but rejects
{ "name": "Alice", "age": 30, "extra": true }
.
Validating the schema itself
Always validate schemas at startup:
const
validator
=
ZSchema
.
create
(
)
;
try
{
validator
.
validateSchema
(
schema
)
;
}
catch
(
err
)
{
console
.
log
(
'Schema errors:'
,
err
.
details
)
;
}
Common mistakes
Forgetting
additionalProperties
By default, extra properties are allowed. Set
additionalProperties: false
or use
unevaluatedProperties: false
to reject them.
Using
additionalProperties: false
with
allOf
This blocks properties from sibling schemas. Use
unevaluatedProperties: false
at the top level instead (draft-2019-09+).
Array
items
in draft-2020-12
Use
prefixItems
for tuple validation.
items
now means "schema for remaining items".
Missing
$schema
Without it, z-schema uses its configured default draft. Include
$schema
for explicit draft targeting.
definitions
vs
$defs
Both work, but $defs is the canonical form in draft-2019-09+. Use it consistently.
返回排行榜