encoding/json/v2(encoding/json/jsontext) — stable in Go 1.27 standard library.refOrValue[T, O](ref.go) — generic type backing the*Refaliases of every object but Schema (HeaderRef, ResponseRef, etc.). Implements customUnmarshalJSONFrom/MarshalJSONTo. Probes for$refby attempting to unmarshal asReference; falls back to the value type if$refis absent.loader(loader.go) — two-pass load: unmarshal →collectResolveRefs(collect component schemas, then resolve all$refs).Schema.Refis the JSON Schema$refkeyword, as OAS 3.1 defines it: a schema that refers to another is a*Schemalike any other, so it can carry sibling keywords (deprecated,description, …), which apply in addition to the target, and a component schema can be just a reference.SchemaRefholds the$ref'sIdentifierand, once loaded, its target asValue; nothing follows it recursively.$refis written after the keywords beside it.- A schema's place in
components.schemasor an object'spropertiesis kept on theSchemaitself, so a whole-struct assignment*s = *vmoves s to wherever v was.Schema.Replacecopies v into s and keeps s's place. - Schema cycles (
schema_cycle.go): a schema may lead back to itself throughproperties,itemsoradditionalProperties, since each step descends into the value, which is how a tree or a list is described. A cycle through$ref,allOf,anyOf,oneOfornotalone never descends, and JSON Schema leaves it undefined, so the loader rejects it and names the cycle. A document built in code is not checked; code that followsRef.Valueshould keep a visited set, asderefTypedoes. Discriminator.Mappingmaps payload values to component schemas, each written as a bare name or a reference;MappingRefturns either into a reference. The loader checks every value resolves, but keeps it as written, so code that renames or redirects a schema must rewrite mapping values as well asSchema.Ref. A discriminator needsoneOf,anyOforallOfbeside it, except on a component schema that another component extends throughallOf, the parent the specification allows it on;Components.Validateknows which those are and passes it to each schema's validation.Schema.PropertyNamesis a schema likeItems: walkers that visit every schema should visit it too. It constrains an object's keys, not the object itself, so it is not part of the cycle check.- Unknown schema keywords fail validation. A keyword the library does not model lands in
Extensionson load, andValidaterejects anything there without anx-prefix, so an unsupported keyword is reported instead of being carried along unseen. Schema.Enumis[]jsontext.Value,Schema.ConstandSchema.Defaultarejsontext.Value— raw JSON is preserved exactly as written. Kind-based validation (enumKindMatchesType,isJSONInteger) checks types without decoding to Go values.Schema(un)marshalling (schema_json.go) — decodes throughschemaJSON, whose shallowertypefield overrides the embedded one: atypeof[X, "null"]becomesTypeX withNullableset. An array of several non-null types fails to decode.Schema.Typeis optional (JSON Schema 2020-12): without it a schema constrains no type, and the empty schema accepts any value. Keywords tied to one type (properties,items,format,pattern, …) are allowed without it, each applying only to instances of its type (JSON Schema 2020-12 core, §7.6.1), and are still validated;Validaterejects them only where they contradict an explicittype. Without a type,requiredmay name properties the schema does not declare, as in ananyOfbranch that only demands a key. An array needs noitems: without it, any items are allowed, which is how an array only ever seen empty is described (maxItems: 0).Schema.AdditionalPropertiesis*AdditionalProperties: a schema for the extra properties' values, or a bare boolean. A nil pointer means the keyword is absent, which is not the same astruedownstream.- Patterns (
pattern.go) are compiled with Go's regexp (RE2).jsonOptstranslates ECMA-262 escapes RE2 spells differently on load, and back on write, so a pattern round-trips as written. Marshalling withoutjsonOptswrites the RE2 form. - Empty values — a list or map whose empty value means the same as its absence, or is invalid, is
omitempty, so code that empties one writes nothing. One whose empty value means something isomitzeroand written whenever it is non-nil:security(no requirements),enum(no valid value),pathsandwebhooks(count towards the required "at least one of"), and path-item and operationservers(an override the specification does not define as empty).