Documentation
¶
Overview ¶
Package genjsonschema builds a JSON Schema (Draft 2020-12) by reflecting over Go type definitions. It powers OPA's `genplanschema` and `genmanifestschema` commands: each generator wraps a Builder, plugs in a TypeResolver for its domain-specific shapes, walks a root struct, and renders the accumulated $defs.
The Builder treats struct types as named definitions referenced via `#/$defs/<TypeName>`, and reflects fields based on their `json:"..."` tags (handling `omitempty`, embedded structs, and skipping unexported fields).
Index ¶
- func MakeNullable(schema any) any
- type Builder
- func (b *Builder) AddNamedDef(name string, schema OrderedMap) (string, error)
- func (b *Builder) AddStruct(t reflect.Type) (string, error)
- func (b *Builder) AllowAdditionalProperties(t reflect.Type)
- func (*Builder) DefRef(name string) string
- func (b *Builder) DefsOrdered() OrderedMap
- func (b *Builder) HasDef(name string) bool
- func (b *Builder) ReflectType(t reflect.Type) (any, error)
- func (b *Builder) Reserve(name string) bool
- func (b *Builder) SetDef(name string, schema OrderedMap)
- type Entry
- type OrderedMap
- type TypeResolver
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MakeNullable ¶
MakeNullable returns a schema equivalent to the input that also accepts the JSON null value.
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
Builder accumulates struct definitions in $defs and offers ReflectType / AddStruct entry points used by both the caller and its TypeResolver.
func NewBuilder ¶
func NewBuilder(resolver TypeResolver) *Builder
NewBuilder returns a Builder. resolver may be nil, in which case only the built-in cases are used.
func (*Builder) AddNamedDef ¶
func (b *Builder) AddNamedDef(name string, schema OrderedMap) (string, error)
AddNamedDef stores schema under name and returns DefRef(name). Use when the body has no recursive references back to itself. Returns an error if name is already registered (whether via Reserve, SetDef, AddNamedDef, or AddStruct) — collisions are always a programming error in this API.
func (*Builder) AddStruct ¶
AddStruct ensures t (a struct or pointer-to-struct) has a definition in $defs and returns its $ref. Recurses through fields, consulting the resolver for each.
func (*Builder) AllowAdditionalProperties ¶
AllowAdditionalProperties opts t out of the default `additionalProperties: false` constraint, so the generated schema accepts unknown keys on that struct. Use this for top-level types whose runtime decoder is lenient and where embedders are known to attach custom fields (e.g. the bundle Manifest).
func (*Builder) DefRef ¶
DefRef returns the JSON pointer ref ("#/$defs/Name") for name. It does not check that the def exists — useful for forward references that will be filled in later.
func (*Builder) DefsOrdered ¶
func (b *Builder) DefsOrdered() OrderedMap
DefsOrdered returns the accumulated $defs in name-sorted order so the rendered schema is byte-stable across runs.
func (*Builder) HasDef ¶
HasDef reports whether name is currently registered (including reserved but not yet filled in).
func (*Builder) ReflectType ¶
ReflectType returns a JSON Schema fragment describing t. Pointers are unwrapped. The resolver, if any, is consulted before built-in handling.
Built-in handling covers: bool, all integer kinds, all float kinds, string, slice/array (item type recurses), map (string-keyed only; values recurse), the bare-`any` interface (matches anything), and named structs (which recurse through AddStruct).
func (*Builder) Reserve ¶
Reserve marks name as in-flight so recursive references emitted while building its body can resolve to a $ref instead of looping. Returns true if the name was newly reserved, false if it already existed (in which case the caller should not call SetDef).
func (*Builder) SetDef ¶
func (b *Builder) SetDef(name string, schema OrderedMap)
SetDef stores schema under name. Typically paired with Reserve.
type OrderedMap ¶
type OrderedMap []Entry
OrderedMap preserves insertion order for JSON object encoding so the generated schema is byte-stable across runs.
func Map ¶
func Map(pairs ...any) OrderedMap
Map builds an OrderedMap from alternating key/value arguments. Keys must be strings; the function panics on an odd number of arguments or on a non-string key. Use this from outside the package to avoid the govet "composites" warning that fires on cross-package struct literals.
Map panics rather than returning an error so it can be used as a literal constructor in deeply nested expressions without breaking the call-site readability that is its whole point. The conditions it panics on are programming errors in literal arguments, not runtime data conditions a caller could usefully handle.
func (OrderedMap) MarshalJSON ¶
func (m OrderedMap) MarshalJSON() ([]byte, error)
type TypeResolver ¶
TypeResolver returns a JSON Schema for t and reports handled=true to short circuit the Builder's default handling. A resolver runs first on every type the Builder visits via ReflectType (after pointer unwrapping), so it can intercept polymorphic interfaces, opaque types, and named structs whose JSON shape isn't derivable from reflection alone.
A resolver that reports handled=true must return a non-nil schema; the Builder treats a nil schema with handled=true as an error so silent JSON `null` output is impossible.
The Builder is passed in so resolvers can recurse — e.g., to translate the underlying type of a polymorphic union and accumulate further $defs.