安装
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.
← 返回排行榜