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}