Documentation
¶
Overview ¶
Package jsonschema builds and checks JSON Schema documents.
It exists for one reason: a schema written as JSON in a string is a schema nothing checks, and the first time it is wrong the caller sends a value the program ignores. Here a schema is a value the compiler knows the shape of, and the same value both renders the document and validates against it, so the two cannot disagree.
The whole surface is a builder and one function:
schema := jsonschema.Object(
jsonschema.Prop("status", jsonschema.String().
Description("Which posts to list").
Enum("published", "draft").
Required()),
jsonschema.Prop("limit", jsonschema.Integer().Min(1).Max(100)),
)
if err := jsonschema.Validate(schema, decoded); err != nil {
// every problem, in one error
}
Two callers, one shape of the same need ¶
A model asked to fill in a tool call, and a model asked to write a module specification, are the same problem: something outside the program produces JSON, and the program has to refuse what it did not ask for before any of it reaches application code. Both callers used to carry their own schema code.
What this package is not ¶
It is not the validation package. That one checks a request or a struct against rule strings and produces a sentence for a person. This one checks decoded JSON against a schema document, before a handler runs, and produces a sentence for a machine. Neither is implemented in terms of the other, and neither grows the other's vocabulary.
Objects are closed ¶
An object refuses a property it did not declare, and says so in the rendered document with additionalProperties: false. JSON Schema's own default is the opposite, and the default is wrong for this job: a producer that invents a property and is never told keeps inventing it.
Reading a schema this package did not write ¶
Deserialize is the other direction, and FromArray is the same thing from an already-decoded map. It reads a document into the same values the builder produces, so a schema that arrived as JSON is checked by the same Validate as one written in Go.
It reads the subset this package can represent, and every keyword outside it is an error naming the keyword rather than a silent drop. There is no Parse that takes bytes: encoding/json.Unmarshal into a map[string]any is the decoder, and a second one here would be a second answer to what the document says.
Where the types live ¶
The types are the package itself, so the call reads jsonschema.String(). The sub-package hesape/jsonschema/types holds no types and exists only to say so: splitting them out would put half a schema behind a second import path for no gain, and Validate switches over a closed set that has to be declared where it is checked.
Index ¶
- Constants
- func Serialize(t Type) (map[string]any, error)
- func Validate(schema Type, value any) error
- type AnyOfType
- func (b *AnyOfType) Description(v string) T
- func (t *AnyOfType) MarshalJSON() ([]byte, error)
- func (b *AnyOfType) Nullable() T
- func (t *AnyOfType) Options() []Type
- func (b *AnyOfType) Required() T
- func (b *AnyOfType) Title(v string) T
- func (b *AnyOfType) ToArray() (map[string]any, error)
- func (b *AnyOfType) ToString() (string, error)
- type ArrayType
- func (t *ArrayType) Default(v []any) *ArrayType
- func (b *ArrayType) Description(v string) T
- func (t *ArrayType) Items(item Type) *ArrayType
- func (t *ArrayType) MarshalJSON() ([]byte, error)
- func (t *ArrayType) Max(v int) *ArrayType
- func (t *ArrayType) Min(v int) *ArrayType
- func (b *ArrayType) Nullable() T
- func (b *ArrayType) Required() T
- func (b *ArrayType) Title(v string) T
- func (b *ArrayType) ToArray() (map[string]any, error)
- func (b *ArrayType) ToString() (string, error)
- func (t *ArrayType) Unique() *ArrayType
- type BooleanType
- func (t *BooleanType) Default(v bool) *BooleanType
- func (b *BooleanType) Description(v string) T
- func (t *BooleanType) MarshalJSON() ([]byte, error)
- func (b *BooleanType) Nullable() T
- func (b *BooleanType) Required() T
- func (b *BooleanType) Title(v string) T
- func (b *BooleanType) ToArray() (map[string]any, error)
- func (b *BooleanType) ToString() (string, error)
- type Document
- type IntegerType
- func (t *IntegerType) Default(v int) *IntegerType
- func (b *IntegerType) Description(v string) T
- func (t *IntegerType) Enum(values ...int) *IntegerType
- func (t *IntegerType) MarshalJSON() ([]byte, error)
- func (t *IntegerType) Max(v int) *IntegerType
- func (t *IntegerType) Min(v int) *IntegerType
- func (t *IntegerType) MultipleOf(v int) *IntegerType
- func (b *IntegerType) Nullable() T
- func (b *IntegerType) Required() T
- func (b *IntegerType) Title(v string) T
- func (b *IntegerType) ToArray() (map[string]any, error)
- func (b *IntegerType) ToString() (string, error)
- type Invalid
- type NumberType
- func (t *NumberType) Default(v float64) *NumberType
- func (b *NumberType) Description(v string) T
- func (t *NumberType) Enum(values ...float64) *NumberType
- func (t *NumberType) MarshalJSON() ([]byte, error)
- func (t *NumberType) Max(v float64) *NumberType
- func (t *NumberType) Min(v float64) *NumberType
- func (t *NumberType) MultipleOf(v float64) *NumberType
- func (b *NumberType) Nullable() T
- func (b *NumberType) Required() T
- func (b *NumberType) Title(v string) T
- func (b *NumberType) ToArray() (map[string]any, error)
- func (b *NumberType) ToString() (string, error)
- type ObjectType
- func (t *ObjectType) Default(v map[string]any) *ObjectType
- func (b *ObjectType) Description(v string) T
- func (t *ObjectType) MarshalJSON() ([]byte, error)
- func (b *ObjectType) Nullable() T
- func (t *ObjectType) Properties() []Property
- func (b *ObjectType) Required() T
- func (b *ObjectType) Title(v string) T
- func (b *ObjectType) ToArray() (map[string]any, error)
- func (b *ObjectType) ToString() (string, error)
- func (t *ObjectType) WithoutAdditionalProperties() *ObjectType
- type Problem
- type Property
- type StringType
- func (t *StringType) Default(v string) *StringType
- func (b *StringType) Description(v string) T
- func (t *StringType) Enum(values ...string) *StringType
- func (t *StringType) Format(v string) *StringType
- func (t *StringType) MarshalJSON() ([]byte, error)
- func (t *StringType) Max(v int) *StringType
- func (t *StringType) Min(v int) *StringType
- func (b *StringType) Nullable() T
- func (t *StringType) Pattern(expr string) *StringType
- func (b *StringType) Required() T
- func (b *StringType) Title(v string) T
- func (b *StringType) ToArray() (map[string]any, error)
- func (b *StringType) ToString() (string, error)
- type Type
- type UnionType
- func (b *UnionType) Description(v string) T
- func (t *UnionType) MarshalJSON() ([]byte, error)
- func (b *UnionType) Nullable() T
- func (b *UnionType) Required() T
- func (b *UnionType) Title(v string) T
- func (b *UnionType) ToArray() (map[string]any, error)
- func (b *UnionType) ToString() (string, error)
- func (t *UnionType) Types() []string
Constants ¶
const Draft = "https://json-schema.org/draft/2020-12/schema"
Draft is the JSON Schema dialect every Document declares.
Variables ¶
This section is empty.
Functions ¶
func Serialize ¶
Serialize renders a type as the map form of its schema document.
The document is produced by marshalling the type and decoding the result, so there is one renderer and not two: the map this returns and the bytes encoding/json.Marshal writes cannot disagree about what the schema says. The cost is that a map decoded from JSON holds every number as a float64, so a minLength of 3 reads back as float64(3). Deserialize takes it either way.
The key order the types chose is lost, because a Go map has none. The bytes keep it; marshal the type when the order matters.
AnyOfType renders as anyOf rather than failing: it is a schema this package can both write and check, and refusing to serialize what it can validate would be a document that disagrees with the program.
func Validate ¶
Validate checks a decoded JSON value against a schema.
The value is what encoding/json produces for an any: map[string]any, []any, string, float64, bool or nil. It is checked before a handler runs, which is what lets that handler read a declared field without checking it, and what stops a value nobody declared from reaching application code.
Every problem is reported at once, in the order the schema declares them. A producer told one mistake per attempt spends three attempts on a form it could have filled in on the second.
Types ¶
type AnyOfType ¶
type AnyOfType struct {
// contains filtered or unexported fields
}
AnyOfType is a value that must satisfy at least one of several schemas.
func (*AnyOfType) Description ¶
func (b *AnyOfType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*AnyOfType) MarshalJSON ¶
MarshalJSON renders the alternatives. A nullable AnyOf carries null as one more alternative, because there is no kind to add it to.
func (*AnyOfType) Nullable ¶
func (b *AnyOfType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*AnyOfType) Required ¶
func (b *AnyOfType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*AnyOfType) Title ¶
func (b *AnyOfType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*AnyOfType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.
type ArrayType ¶
type ArrayType struct {
// contains filtered or unexported fields
}
ArrayType is an ordered list.
func Array ¶
func Array() *ArrayType
Array builds an array type. Call Items to say what the elements are; an array with no Items accepts any element.
func (*ArrayType) Description ¶
func (b *ArrayType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*ArrayType) MarshalJSON ¶
MarshalJSON renders the array, its constraints and its element schema.
func (*ArrayType) Nullable ¶
func (b *ArrayType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*ArrayType) Required ¶
func (b *ArrayType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*ArrayType) Title ¶
func (b *ArrayType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*ArrayType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.
type BooleanType ¶
type BooleanType struct {
// contains filtered or unexported fields
}
BooleanType is true or false.
func (*BooleanType) Default ¶
func (t *BooleanType) Default(v bool) *BooleanType
Default sets the value used when the property is absent.
func (*BooleanType) Description ¶
func (b *BooleanType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*BooleanType) MarshalJSON ¶
func (t *BooleanType) MarshalJSON() ([]byte, error)
MarshalJSON renders the boolean.
func (*BooleanType) Nullable ¶
func (b *BooleanType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*BooleanType) Required ¶
func (b *BooleanType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*BooleanType) Title ¶
func (b *BooleanType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*BooleanType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.
type Document ¶
type Document struct {
// ID is the address the document is published at. It renders as $id.
ID string
// Root is the schema itself. A Document without one is an error.
Root Type
// Examples are whole values that satisfy Root. They are the cheapest
// instruction a producer gets, and worth one.
Examples []any
}
Document is a schema published on its own: a root type, plus the keywords that let a reader say which dialect it is written in and where it came from.
It renders as one object -- the identity keywords and the root's own keywords side by side -- which is the shape a schema file has:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.test/module.schema.json",
"type": "object",
"properties": { ... }
}
Title and description belong to Root. There is one place to write them.
func (Document) MarshalJSON ¶
MarshalJSON renders the document. Use encoding/json.MarshalIndent to write it to a file; the indenter reads this output like any other.
type IntegerType ¶
type IntegerType struct {
// contains filtered or unexported fields
}
IntegerType is a whole number.
func (*IntegerType) Default ¶
func (t *IntegerType) Default(v int) *IntegerType
Default sets the value used when the property is absent.
func (*IntegerType) Description ¶
func (b *IntegerType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*IntegerType) Enum ¶
func (t *IntegerType) Enum(values ...int) *IntegerType
Enum limits the value to a set.
func (*IntegerType) MarshalJSON ¶
func (t *IntegerType) MarshalJSON() ([]byte, error)
MarshalJSON renders the integer and its constraints.
func (*IntegerType) Max ¶
func (t *IntegerType) Max(v int) *IntegerType
Max sets the maximum value, inclusive.
func (*IntegerType) Min ¶
func (t *IntegerType) Min(v int) *IntegerType
Min sets the minimum value, inclusive.
func (*IntegerType) MultipleOf ¶
func (t *IntegerType) MultipleOf(v int) *IntegerType
MultipleOf requires the value to be a multiple of v.
func (*IntegerType) Nullable ¶
func (b *IntegerType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*IntegerType) Required ¶
func (b *IntegerType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*IntegerType) Title ¶
func (b *IntegerType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*IntegerType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.
type Invalid ¶
type Invalid struct {
Problems []Problem
}
Invalid is the error Validate returns. It carries every problem, so a caller that wants to act on one field can, and a caller that only prints gets the whole answer from Error.
type NumberType ¶
type NumberType struct {
// contains filtered or unexported fields
}
NumberType is a number, whole or fractional.
func (*NumberType) Default ¶
func (t *NumberType) Default(v float64) *NumberType
Default sets the value used when the property is absent.
func (*NumberType) Description ¶
func (b *NumberType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*NumberType) Enum ¶
func (t *NumberType) Enum(values ...float64) *NumberType
Enum limits the value to a set.
func (*NumberType) MarshalJSON ¶
func (t *NumberType) MarshalJSON() ([]byte, error)
MarshalJSON renders the number and its constraints.
func (*NumberType) Max ¶
func (t *NumberType) Max(v float64) *NumberType
Max sets the maximum value, inclusive.
func (*NumberType) Min ¶
func (t *NumberType) Min(v float64) *NumberType
Min sets the minimum value, inclusive.
func (*NumberType) MultipleOf ¶
func (t *NumberType) MultipleOf(v float64) *NumberType
MultipleOf requires the value to be a multiple of v, and renders as the multipleOf keyword.
The check is exact arithmetic on a binary float, and 0.1 is not representable in one: a rule written as MultipleOf(0.01) for money will refuse amounts that are correct. Money is an integer of cents, and IntegerType.MultipleOf is the rule for it. This is here because JSON Schema has the keyword for numbers and a document that carries it has to survive Deserialize and render back unchanged.
func (*NumberType) Nullable ¶
func (b *NumberType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*NumberType) Required ¶
func (b *NumberType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*NumberType) Title ¶
func (b *NumberType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*NumberType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.
type ObjectType ¶
type ObjectType struct {
// contains filtered or unexported fields
}
ObjectType is a value with named properties.
An object refuses a property it did not declare. See the package comment for why that is the default and not a switch.
func Object ¶
func Object(properties ...Property) *ObjectType
Object builds an object from its properties, in the order given.
The properties are taken in order, because a Go map has none and a schema whose properties render differently on two runs is a schema nobody can diff.
The object is closed: additionalProperties renders as false. That is this package's default and not JSON Schema's -- see the package comment. ObjectType.WithoutAdditionalProperties is the same thing said out loud.
func (*ObjectType) Default ¶
func (t *ObjectType) Default(v map[string]any) *ObjectType
Default sets the value used when the property is absent.
func (*ObjectType) Description ¶
func (b *ObjectType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*ObjectType) MarshalJSON ¶
func (t *ObjectType) MarshalJSON() ([]byte, error)
MarshalJSON renders the object, its properties in declaration order, and the names of the properties marked Required.
func (*ObjectType) Nullable ¶
func (b *ObjectType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*ObjectType) Properties ¶
func (t *ObjectType) Properties() []Property
Properties returns the object's properties in declaration order.
It is here so a caller can print or walk a schema without decoding the document it just rendered.
func (*ObjectType) Required ¶
func (b *ObjectType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*ObjectType) Title ¶
func (b *ObjectType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*ObjectType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.
func (*ObjectType) WithoutAdditionalProperties ¶
func (t *ObjectType) WithoutAdditionalProperties() *ObjectType
WithoutAdditionalProperties disallows properties the object did not declare. It closes the object: additionalProperties renders as false.
It is already true of every object Object builds, so calling it changes nothing and is not required. It exists so a schema can say it explicitly, and because an object that came back from Deserialize open is closed by exactly this call.
type Problem ¶
type Problem struct {
// Path is where the problem is, in dotted form: "filters.tag",
// "tags[2]". It is empty for the value handed to Validate.
Path string
// Message is what is wrong with it, as a predicate: "is required",
// "must be a string".
Message string
}
Problem is one thing wrong with a value.
type Property ¶
type Property struct {
// Name is the key the value appears under.
Name string
// Type is the schema the value must satisfy.
Type Type
}
Property is one named member of an object.
type StringType ¶
type StringType struct {
// contains filtered or unexported fields
}
StringType is a text value.
func (*StringType) Default ¶
func (t *StringType) Default(v string) *StringType
Default sets the value used when the property is absent.
func (*StringType) Description ¶
func (b *StringType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*StringType) Enum ¶
func (t *StringType) Enum(values ...string) *StringType
Enum limits the value to a set.
It is worth reaching for. A producer given a closed list picks from it, and a producer given "the status" invents one.
func (*StringType) Format ¶
func (t *StringType) Format(v string) *StringType
Format records one of JSON Schema's built-in formats, such as "email" or "date-time".
It is written into the document and is not checked by Validate: JSON Schema itself defines format as an annotation, and a value refused for a reason the published document does not state is worse than one that is not refused.
func (*StringType) MarshalJSON ¶
func (t *StringType) MarshalJSON() ([]byte, error)
MarshalJSON renders the string and its constraints.
func (*StringType) Max ¶
func (t *StringType) Max(v int) *StringType
Max sets the maximum length in characters, inclusive.
func (*StringType) Min ¶
func (t *StringType) Min(v int) *StringType
Min sets the minimum length in characters, inclusive.
func (*StringType) Nullable ¶
func (b *StringType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*StringType) Pattern ¶
func (t *StringType) Pattern(expr string) *StringType
Pattern sets a regular expression the value must match.
It compiles here rather than at validation time, so a broken expression is a panic where it was written instead of a refusal where it was used.
func (*StringType) Required ¶
func (b *StringType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*StringType) Title ¶
func (b *StringType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*StringType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.
type Type ¶
Type is one node of a schema: the kind a value must have, and the constraints on it.
The set of implementations is closed -- ObjectType, StringType, IntegerType, NumberType, BooleanType, ArrayType, UnionType and AnyOfType. Validate switches on that set, so a ninth shape declared outside this package would be a schema Validate cannot check. The unexported method is what closes it.
func Deserialize ¶
Deserialize builds a type from the supported JSON Schema subset.
It reads what this package writes, and the part of JSON Schema that maps onto it: the six kinds, the type-as-a-list union, local "$ref" pointers, and the nullable "anyOf"/"oneOf" shape that a generator emits for an optional value. Anything outside that subset is an error naming the keyword, never a silent drop -- a schema that deserializes into something weaker than it says is a validator that passes values the document forbids.
What it cannot keep ¶
Property order. A JSON object has none once decoded into a Go map, and ObjectType renders its properties in declaration order, so the properties of a deserialized object are ordered by name. A document round-tripped through Serialize and back therefore renders with its properties sorted; everything else about it is unchanged.
Objects come back as they were written ¶
Object closes an object because that is this package's default (see the package comment). This does not: an object is closed only when the document says additionalProperties is false, because the job here is to read a schema faithfully rather than to tighten one. ObjectType.WithoutAdditionalProperties closes one that came back open.
func FromArray ¶
FromArray builds a type from a raw map of the supported JSON Schema subset. It delegates to Deserialize.
The map is what encoding/json.Unmarshal produces for an any: every number is a float64 and every object is a map[string]any. Serialize produces the same shape, so a document this package rendered reads back through here.
A schema this package cannot represent is an error naming what it could not read.
type UnionType ¶
type UnionType struct {
// contains filtered or unexported fields
}
UnionType is a value that may be any of several primitive kinds. It renders as JSON Schema's type-as-a-list form.
It is the short way to write a value that differs only in kind. When the alternatives differ in more than kind -- one has a pattern, the other a minimum -- they are separate schemas and the answer is AnyOf.
func Union ¶
Union builds a union of the named primitive kinds: string, integer, number, boolean, object or array. The name "null" is accepted and marks the union nullable.
An unsupported name panics. A schema is written once, at start-up, and a typo there is a mistake in the program, not in the data. Deserialize reads names out of a document rather than out of a program and gets an error for the same input.
func (*UnionType) Description ¶
func (b *UnionType) Description(v string) T
Description says what the value is for.
It is worth writing on every property. A description is the cheapest thing in the document and it is the only place a producer learns what the program meant by a name.
func (*UnionType) MarshalJSON ¶
MarshalJSON renders the union as a list of type names.
func (*UnionType) Nullable ¶
func (b *UnionType) Nullable() T
Nullable allows the value to be null. Without it, an explicit null is refused like any other wrong kind.
func (*UnionType) Required ¶
func (b *UnionType) Required() T
Required marks the property as mandatory. An object missing it is refused before anything reads it.
It is declared on the property's own type and hoisted into the parent object's required list when the document renders, which is where JSON Schema keeps it.
func (*UnionType) Title ¶
func (b *UnionType) Title(v string) T
Title sets the type's title: a short label for the value, for a reader.
func (*UnionType) ToString ¶
ToString converts the type to its string representation: the schema document as pretty-printed JSON, indented with four spaces.
It renders the type rather than the map [ToArray] returns, so the keys come out in the order the type declares them: type before properties, and properties in the order they were written. A Go map has no order, which is why the two differ.