registry.go

 1package apijson
 2
 3import (
 4	"reflect"
 5
 6	"github.com/tidwall/gjson"
 7)
 8
 9type UnionVariant struct {
10	TypeFilter         gjson.Type
11	DiscriminatorValue interface{}
12	Type               reflect.Type
13}
14
15var unionRegistry = map[reflect.Type]unionEntry{}
16var unionVariants = map[reflect.Type]interface{}{}
17
18type unionEntry struct {
19	discriminatorKey string
20	variants         []UnionVariant
21}
22
23func RegisterUnion[T any](discriminator string, variants ...UnionVariant) {
24	typ := reflect.TypeOf((*T)(nil)).Elem()
25	unionRegistry[typ] = unionEntry{
26		discriminatorKey: discriminator,
27		variants:         variants,
28	}
29	for _, variant := range variants {
30		unionVariants[variant.Type] = typ
31	}
32}
33
34// Useful to wrap a union type to force it to use [apijson.UnmarshalJSON] since you cannot define an
35// UnmarshalJSON function on the interface itself.
36type UnionUnmarshaler[T any] struct {
37	Value T
38}
39
40func (c *UnionUnmarshaler[T]) UnmarshalJSON(buf []byte) error {
41	return UnmarshalRoot(buf, &c.Value)
42}