Interfaces and discriminators
An interface field becomes an anyOf over its registered implementations. A
direct one-dimensional slice of that interface becomes an array with the union
under items.anyOf. The generator writes UnmarshalJSON dispatch code for the
containing struct.
type PaymentMethod interface{ isPaymentMethod() }
type Card struct { Number string `json:"number"`}func (Card) isPaymentMethod() {}
type BankTransfer struct { Account string `json:"account"`}func (*BankTransfer) isPaymentMethod() {}
type Payment struct { Methods []PaymentMethod `json:"methods"`}Register the field, its implementations, and optionally a custom discriminator:
var _ = jsonschema.NewJSONSchemaMethod( Payment.Schema, jsonschema.WithInterface( Payment{}.Methods, jsonschema.Discriminator("!kind"), jsonschema.Impl("card", Card{}), jsonschema.Impl("bank_transfer", (*BankTransfer)(nil)), ),)Impl keeps each implementation next to its stable wire discriminator. The
default discriminator property is !type. The compatible split form using
WithInterfaceImpls and WithDiscriminator remains supported; without
explicit Impl values, wire discriminators derive from Go type names. Each
implementation’s JSON must carry the discriminator expected by the generated
unmarshaler. Slice elements are decoded in order, and an invalid element reports
its zero-based index without partially assigning the destination slice.
Value and pointer implementations remain value and pointer values after decoding. A successful decode assigns the containing struct only after all registered interface fields and slice elements decode successfully.
Marshaling interface values
Section titled “Marshaling interface values”The generator writes UnmarshalJSON dispatch code. It does not add a
discriminator when concrete implementations are marshaled. If decoded values
must round-trip into schema-valid JSON, make each implementation emit the same
discriminator required by the schema:
func (c Card) MarshalJSON() ([]byte, error) { type plain Card return json.Marshal(struct { Kind string `json:"!kind"` plain }{Kind: "card", plain: plain(c)})}Without this method, ordinary json.Marshal emits the concrete fields but not
!kind, so the result cannot be decoded by the generated union unmarshaler and
does not satisfy the generated union schema.
The slice must be the direct field type. Fixed arrays, nested slices, named
slice containers, Optional[[]I], Nullable[[]I], and inline interface
declarations are rejected.
An Optional[I] scalar interface field is supported. Nullable[I] is not.
See the compiling examples/sealed_interface_slices
package for schema and runtime coverage, including value and pointer
implementations.