Documentation
¶
Overview ¶
Package jsonschema is an implementation of the JSON Schema specification, a JSON-based format for describing the structure of JSON data. The package can be used to read schemas for code generation, and to validate data using the draft 2020-12 specification. Validation with other drafts or custom meta-schemas is not supported.
Construct a Schema as you would any Go struct (for example, by writing a struct literal), or unmarshal a JSON schema into a Schema in the usual way (with encoding/json, for instance). It can then be used for code generation or other purposes without further processing. You can also infer a schema from a Go struct.
Resolution ¶
A Schema can refer to other schemas, both inside and outside itself. These references must be resolved before a schema can be used for validation. Call Schema.Resolve to obtain a resolved schema (called a Resolved). If the schema has external references, pass a ResolveOptions with a Loader to load them. To validate default values in a schema, set [ResolveOptions.ValidateDefaults] to true.
Validation ¶
Call Resolved.Validate to validate a JSON value. The value must be a Go value that looks like the result of unmarshaling a JSON value into an [any] or a struct. For example, the JSON value
{"name": "Al", "scores": [90, 80, 100]}
could be represented as the Go value
map[string]any{ "name": "Al", "scores": []any{90, 80, 100}, }
or as a value of this type:
type Player struct { Name string `json:"name"` Scores []int `json:"scores"` }
Inference ¶
The For function returns a Schema describing the given Go type. Each field in the struct becomes a property of the schema. The values of "json" tags are respected: the field's property name is taken from the tag, and fields omitted from the JSON are omitted from the schema as well. For example, `jsonschema.For[Player]()` returns this schema:
{ "properties": { "name": { "type": "string" }, "scores": { "type": "array", "items": {"type": "integer"} } "required": ["name", "scores"], "additionalProperties": {"not": {}} } }
Use the "jsonschema" struct tag to provide a description for the property:
type Player struct { Name string `json:"name" jsonschema:"player name"` Scores []int `json:"scores" jsonschema:"scores of player's games"` }
Deviations from the specification ¶
Regular expressions are processed with Go's regexp package, which differs from ECMA 262, most significantly in not supporting back-references. See this table of differences for more.
The "format" keyword described in section 7 of the validation spec is recorded in the Schema, but is ignored during validation. It does not even produce annotations. Use the "pattern" keyword instead: it will work more reliably across JSON Schema implementations. See learnjsonschema.com for more recommendations about "format".
The content keywords described in section 8 of the validation spec are recorded in the schema, but ignored during validation.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Equal ¶
Equal reports whether two Go values representing JSON values are equal according to the JSON Schema spec. The values must not contain cycles. See https://json-schema.org/draft/2020-12/json-schema-core#section-4.2.2. It behaves like reflect.DeepEqual, except that numbers are compared according to mathematical equality.
Types ¶
type ForOptions ¶
type ForOptions struct { // If IgnoreInvalidTypes is true, fields that can't be represented as a JSON // Schema are ignored instead of causing an error. // This allows callers to adjust the resulting schema using custom knowledge. // For example, an interface type where all the possible implementations are // known can be described with "oneof". IgnoreInvalidTypes bool // TypeSchemas maps types to their schemas. // If [For] encounters a type equal to a type of a key in this map, the // corresponding value is used as the resulting schema (after cloning to // ensure uniqueness). // Types in this map override the default translations, as described // in [For]'s documentation. TypeSchemas map[any]*Schema }
type ResolveOptions ¶
type ResolveOptions struct { // BaseURI is the URI relative to which the root schema should be resolved. // If non-empty, must be an absolute URI (one that starts with a scheme). // It is resolved (in the URI sense; see [url.ResolveReference]) with root's // $id property. // If the resulting URI is not absolute, then the schema cannot contain // relative URI references. BaseURI string // Loader loads schemas that are referred to by a $ref but are not under the // root schema (remote references). // If nil, resolving a remote reference will return an error. Loader Loader // ValidateDefaults determines whether to validate values of "default" keywords // against their schemas. // The [JSON Schema specification] does not require this, but it is recommended // if defaults will be used. // // [JSON Schema specification]: https://json-schema.org/understanding-json-schema/reference/annotations ValidateDefaults bool }
ResolveOptions are options for Schema.Resolve.
type Resolved ¶
type Resolved struct {
// contains filtered or unexported fields
}
A Resolved consists of a Schema along with associated information needed to validate documents against it. A Resolved has been validated against its meta-schema, and all its references (the $ref and $dynamicRef keywords) have been resolved to their referenced Schemas. Call Schema.Resolve to obtain a Resolved from a Schema.
func (*Resolved) ApplyDefaults ¶
ApplyDefaults modifies an instance by applying the schema's defaults to it. If a schema or sub-schema has a default, then a corresponding zero instance value is set to the default.
The JSON Schema specification does not describe how defaults should be interpreted. This method honors defaults only on properties, and only those that are not required. If the instance is a map and the property is missing, the property is added to the map with the default. If the instance is a struct, the field corresponding to the property exists, and its value is zero, the field is set to the default. ApplyDefaults can panic if a default cannot be assigned to a field.
The argument must be a pointer to the instance. (In case we decide that top-level defaults are meaningful.)
It is recommended to first call Resolve with a ValidateDefaults option of true, then call this method, and lastly call Validate.
type Schema ¶
type Schema struct { // core ID string `json:"$id,omitempty"` Schema string `json:"$schema,omitempty"` Ref string `json:"$ref,omitempty"` Comment string `json:"$comment,omitempty"` Defs map[string]*Schema `json:"$defs,omitempty"` // definitions is deprecated but still allowed. It is a synonym for $defs. Definitions map[string]*Schema `json:"definitions,omitempty"` Anchor string `json:"$anchor,omitempty"` DynamicAnchor string `json:"$dynamicAnchor,omitempty"` DynamicRef string `json:"$dynamicRef,omitempty"` Vocabulary map[string]bool `json:"$vocabulary,omitempty"` // metadata Title string `json:"title,omitempty"` Description string `json:"description,omitempty"` Default json.RawMessage `json:"default,omitempty"` Deprecated bool `json:"deprecated,omitempty"` ReadOnly bool `json:"readOnly,omitempty"` WriteOnly bool `json:"writeOnly,omitempty"` Examples []any `json:"examples,omitempty"` // validation // Use Type for a single type, or Types for multiple types; never both. Type string `json:"-"` Types []string `json:"-"` Enum []any `json:"enum,omitempty"` // Const is *any because a JSON null (Go nil) is a valid value. Const *any `json:"const,omitempty"` MultipleOf *float64 `json:"multipleOf,omitempty"` Minimum *float64 `json:"minimum,omitempty"` Maximum *float64 `json:"maximum,omitempty"` ExclusiveMinimum *float64 `json:"exclusiveMinimum,omitempty"` ExclusiveMaximum *float64 `json:"exclusiveMaximum,omitempty"` MinLength *int `json:"minLength,omitempty"` MaxLength *int `json:"maxLength,omitempty"` Pattern string `json:"pattern,omitempty"` // arrays PrefixItems []*Schema `json:"prefixItems,omitempty"` Items *Schema `json:"items,omitempty"` MinItems *int `json:"minItems,omitempty"` MaxItems *int `json:"maxItems,omitempty"` AdditionalItems *Schema `json:"additionalItems,omitempty"` UniqueItems bool `json:"uniqueItems,omitempty"` Contains *Schema `json:"contains,omitempty"` MinContains *int `json:"minContains,omitempty"` // *int, not int: default is 1, not 0 MaxContains *int `json:"maxContains,omitempty"` UnevaluatedItems *Schema `json:"unevaluatedItems,omitempty"` // objects MinProperties *int `json:"minProperties,omitempty"` MaxProperties *int `json:"maxProperties,omitempty"` Required []string `json:"required,omitempty"` DependentRequired map[string][]string `json:"dependentRequired,omitempty"` Properties map[string]*Schema `json:"properties,omitempty"` PatternProperties map[string]*Schema `json:"patternProperties,omitempty"` AdditionalProperties *Schema `json:"additionalProperties,omitempty"` PropertyNames *Schema `json:"propertyNames,omitempty"` UnevaluatedProperties *Schema `json:"unevaluatedProperties,omitempty"` // logic AllOf []*Schema `json:"allOf,omitempty"` AnyOf []*Schema `json:"anyOf,omitempty"` OneOf []*Schema `json:"oneOf,omitempty"` Not *Schema `json:"not,omitempty"` // conditional If *Schema `json:"if,omitempty"` Then *Schema `json:"then,omitempty"` Else *Schema `json:"else,omitempty"` DependentSchemas map[string]*Schema `json:"dependentSchemas,omitempty"` // other // https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.8 ContentEncoding string `json:"contentEncoding,omitempty"` ContentMediaType string `json:"contentMediaType,omitempty"` ContentSchema *Schema `json:"contentSchema,omitempty"` // https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-00#rfc.section.7 Format string `json:"format,omitempty"` // Extra allows for additional keywords beyond those specified. Extra map[string]any `json:"-"` }
A Schema is a JSON schema object. It corresponds to the 2020-12 draft, as described in https://json-schema.org/draft/2020-12, specifically:
- https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-01
- https://json-schema.org/draft/2020-12/draft-bhutton-json-schema-validation-01
A Schema value may have non-zero values for more than one field: all relevant non-zero fields are used for validation. There is one exception to provide more Go type-safety: the Type and Types fields are mutually exclusive.
Since this struct is a Go representation of a JSON value, it inherits JSON's distinction between nil and empty. Nil slices and maps are considered absent, but empty ones are present and affect validation. For example,
Schema{Enum: nil}
is equivalent to an empty schema, so it validates every instance. But
Schema{Enum: []any{}}
requires equality to some slice element, so it vacuously rejects every instance.
func For ¶
func For[T any](opts *ForOptions) (*Schema, error)
It translates Go types into compatible JSON schema types, as follows. These defaults can be overridden by [ForOptions.TypeSchemas].
- Strings have schema type "string".
- Bools have schema type "boolean".
- Signed and unsigned integer types have schema type "integer".
- Floating point types have schema type "number".
- Slices and arrays have schema type "array", and a corresponding schema for items.
- Maps with string key have schema type "object", and corresponding schema for additionalProperties.
- Structs have schema type "object", and disallow additionalProperties. Their properties are derived from exported struct fields, using the struct field JSON name. Fields that are marked "omitempty" are considered optional; all other fields become required properties.
- Some types in the standard library that implement json.Marshaler translate to schemas that match the values to which they marshal. For example, time.Time translates to the schema for strings.
For will return an error if there is a cycle in the types.
By default, For returns an error if t contains (possibly recursively) any of the following Go types, as they are incompatible with the JSON schema spec. If [ForOptions.IgnoreInvalidTypes] is true, then these types are ignored instead.
- maps with key other than 'string'
- function types
- channel types
- complex numbers
- unsafe pointers
This function recognizes struct field tags named "jsonschema". A jsonschema tag on a field is used as the description for the corresponding property. For future compatibility, descriptions must not start with "WORD=", where WORD is a sequence of non-whitespace characters.
func ForType ¶
func ForType(t reflect.Type, opts *ForOptions) (*Schema, error)
ForType is like For, but takes a reflect.Type
func (*Schema) CloneSchemas ¶
CloneSchemas returns a copy of s. The copy is shallow except for sub-schemas, which are themelves copied with CloneSchemas. This allows both s and s.CloneSchemas() to appear as sub-schemas of the same parent.
func (*Schema) MarshalJSON ¶
func (*Schema) Resolve ¶
func (root *Schema) Resolve(opts *ResolveOptions) (*Resolved, error)
Resolve resolves all references within the schema and performs other tasks that prepare the schema for validation. If opts is nil, the default values are used. The schema must not be changed after Resolve is called. The same schema may be resolved multiple times.