Documentation
¶
Overview ¶
Package union provides generic union type implementations for Go with JSON marshaling and unmarshaling support.
This package offers two union types:
- TaggedUnion: A discriminated union with explicit variant/value wrapper
- Union: An untagged union that marshals data directly
TaggedUnion ¶
TaggedUnion represents a discriminated union where the JSON representation includes a variant field indicating which type is active and a value field containing the data.
Example usage:
type Shape struct {
Circle *Circle `variant:"circle"`
Rectangle *Rectangle `variant:"rectangle"`
Triangle *Triangle `variant:"triangle"`
}
var shape union.TaggedUnion[Shape]
shape.Value.Circle = &Circle{Radius: 5.0}
// Marshals to: {"type": "circle", "value": {"radius": 5.0}}
data, _ := json.Marshal(shape)
The `variant` struct tag specifies the variant name in JSON. If no tag is provided, the field name is used (e.g., "Circle" instead of "circle").
Custom field names can be specified by implementing TaggedFieldNames():
func (s Shape) TaggedFieldNames() (variant, value string) {
return "kind", "data"
}
// Marshals to: {"kind": "circle", "data": {...}}
Union ¶
Union represents an untagged union where the JSON representation is the data itself, without any wrapper. When unmarshaling, each field is tried in order until one successfully deserializes to a non-zero value.
Example usage:
type Shape struct {
Circle *Circle
Rectangle *Rectangle
Triangle *Triangle
}
var shape union.Union[Shape]
shape.Value.Circle = &Circle{Radius: 5.0}
// Marshals to: {"radius": 5.0}
data, _ := json.Marshal(shape)
// Unmarshaling tries each field until one produces a non-zero value
_ = json.Unmarshal([]byte(`{"width": 10, "height": 5}`), &shape)
// shape.Value.Rectangle will be set
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type TaggedUnion ¶
type TaggedUnion[Spec any] struct{ Value Spec }
TaggedUnion represents a discriminated union type that can hold one of several variant types defined in the Spec struct. The Spec type should be a struct where each field represents a possible variant of the union.
Only one field in the Spec struct should be non-zero at any time. When marshaling to JSON, the union is represented as an object with a variant field (indicating which variant is active) and a value field (containing the variant's data).
func (TaggedUnion[Spec]) GetValue ¶
func (u TaggedUnion[Spec]) GetValue() any
GetValue returns the value of the active variant in the union. It iterates through all fields in the Spec struct and returns the value of the non-zero field. If no fields are set or multiple fields are set, it returns nil (indicating an invalid state).
func (TaggedUnion[Spec]) MarshalJSON ¶
func (u TaggedUnion[Spec]) MarshalJSON() ([]byte, error)
MarshalJSON implements the json.Marshaler interface. It serializes the union to JSON as an object with two fields:
- A variant field (default "type") containing the variant name
- A value field (default "value") containing the variant's data
The variant name is determined by the struct field's `variant` struct tag, or the field name if no variant is specified.
Returns an error if:
- The Spec type is not a struct
- No fields are set (zero state)
- Multiple fields are set (invalid state)
func (*TaggedUnion[Spec]) UnmarshalJSON ¶
func (u *TaggedUnion[Spec]) UnmarshalJSON(data []byte) error
UnmarshalJSON implements the json.Unmarshaler interface. It deserializes JSON data into the union by:
- Reading the variant field to determine which variant is active
- Unmarshaling the value field into the corresponding struct field
The method handles both pointer and non-pointer fields correctly.
Returns an error if:
- The JSON data is malformed
- The Spec type is not a struct
- The variant or value fields are missing
- The variant field doesn't match any known variant
- Multiple struct fields match the same variant (invalid Spec definition)
- The value cannot be unmarshaled into the target field type
type Union ¶
type Union[Spec any] struct{ Value Spec }
Union represents an untagged union type that can hold one of several variant types defined in the Spec struct. The Spec type should be a struct where each field represents a possible variant of the union.
Only one field in the Spec struct should be non-zero at any time. When marshaling to JSON, the union's data is marshaled directly without a wrapper. When unmarshaling, each field is tried in order until one successfully deserializes to a non-zero value.
func (Union[Spec]) GetValue ¶
GetValue returns the value of the active variant in the union. It iterates through all fields in the Spec struct and returns the value of the non-zero field. If no fields are set or multiple fields are set, it returns nil (indicating an invalid state).
func (Union[Spec]) MarshalJSON ¶
MarshalJSON implements the json.Marshaler interface. It serializes the union's active variant data directly to JSON.
Returns an error if:
- The Spec type is not a struct
- No fields are set (zero state)
- Multiple fields are set (invalid state)
func (*Union[Spec]) UnmarshalJSON ¶
UnmarshalJSON implements the json.Unmarshaler interface. It deserializes JSON data into the union by trying each field in order until one successfully unmarshals to a non-zero value. Uses strict matching to ensure all JSON fields map to struct fields.
Returns an error if:
- The JSON data is malformed
- The Spec type is not a struct
- No field successfully unmarshals to a non-zero value