Documentation
¶
Index ¶
- func Decode(resolver TypeResolver, source map[string]any, output any) error
- func NewPolymorphismBuilder() polymorphismBuilderEmpty
- func NewRuleBuilder() ruleBuilderBase
- func UnmarshalJSON(resolver TypeResolver, data []byte, output any) error
- type Polymorphism
- type Rule
- type RulePolymorphism
- type TypeMap
- type TypeMapPolymorphism
- type TypeResolver
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Decode ¶
func Decode(resolver TypeResolver, source map[string]any, output any) error
Decode the given source map into the given output object using the given TypeResolver and mapstructure. The output object must be a pointer.
func NewPolymorphismBuilder ¶
func NewPolymorphismBuilder() polymorphismBuilderEmpty
NewPolymorphismBuilder creates a new polymorphism builder that is used in a human readable way to create a polymorphism. It only allows a valid combination of rules and type maps.
func NewRuleBuilder ¶
func NewRuleBuilder() ruleBuilderBase
NewRuleBuilder creates a new ruleBuilder. It enables a fluent interface for building a Rule.
func UnmarshalJSON ¶
func UnmarshalJSON(resolver TypeResolver, data []byte, output any) error
UnmarshalJSON unmarshals the given JSON data into the given output object using the given TypeResolver.
Example ¶
ExampleUnmarshalJSON demonstrates how to use the polymorpher to unmarshal a JSON into a struct with a polymorphic field.
package main
import (
"fmt"
"github.com/SoulKa/golymorph"
"reflect"
)
func main() {
// get a JSON that contains a payload with a type field that determines the type of the payload
alertEventJson := `{ "timestamp": "2023-11-27T22:14:09+00:00", "payload": { "type": "alert", "message": "something is broken!" } }`
// the parent type that contains the polymorphic payload
type Event struct {
Timestamp string
Payload any
}
// the polymorphic child types
type AlertPayload struct {
Type string
Message string
}
type PingPayload struct {
Type string
Ip string
}
// define a mapping from the type value to the type of the payload
typeMap := golymorph.TypeMap{
"alert": reflect.TypeOf(AlertPayload{}),
"ping": reflect.TypeOf(PingPayload{}),
}
// create a TypeResolver that assigns the type of the payload based on the type field
err, resolver := golymorph.NewPolymorphismBuilder().
DefineTypeAt("payload").
UsingTypeMap(typeMap).
WithDiscriminatorAt("type").
Build()
if err != nil {
panic(fmt.Sprintf("error building polymorpher: %s", err))
}
// create a new event
var event Event
if err := golymorph.UnmarshalJSON(resolver, []byte(alertEventJson), &event); err != nil {
panic(fmt.Sprintf("error unmarshalling event: %s", err))
}
// continue to work with the event
fmt.Printf("event: %+v\n", event)
fmt.Printf("event payload: %T %+v\n", event.Payload, event.Payload.(AlertPayload))
}
Output: event: {Timestamp:2023-11-27T22:14:09+00:00 Payload:{Type:alert Message:something is broken!}} event payload: golymorph_test.AlertPayload {Type:alert Message:something is broken!}
Types ¶
type Polymorphism ¶
type Polymorphism struct {
// TargetPath is the path to the object to assign the new type to
TargetPath objectpath.ObjectPath
}
Polymorphism is the base struct for all polymorphism mappers. It contains the target path to assign the new type to.
type Rule ¶
type Rule struct {
// ValuePath is the path to the value in the source to compare.
ValuePath objectpath.ObjectPath
// ComparatorFunction is the function to use to compare the value at ValuePath to.
ComparatorFunction func(any) bool
// NewType is the type to assign to the target if the rule matches.
NewType reflect.Type
}
Rule is a rule for a polymorphism mapper.
type RulePolymorphism ¶
type RulePolymorphism struct {
Polymorphism
// Rules is a list of Rules to apply. The first rule that matches is used to determine the target type.
Rules []Rule
}
RulePolymorphism is a mapper that assigns a target type based on the given Rules
func (*RulePolymorphism) AssignTargetType ¶
func (p *RulePolymorphism) AssignTargetType(source any, target any) error
type TypeMapPolymorphism ¶
type TypeMapPolymorphism struct {
Polymorphism
// DiscriminatorPath is the path to the discriminator value
DiscriminatorPath objectpath.ObjectPath
// TypeMap is a map of discriminator values to types
TypeMap TypeMap
}
TypeMapPolymorphism is a mapper that assigns a target type based on a discriminator value and a type map
func (*TypeMapPolymorphism) AssignTargetType ¶
func (p *TypeMapPolymorphism) AssignTargetType(source any, target any) error
Example ¶
ExampleTypeMapPolymorphism_AssignTargetType demonstrates how to use the polymorpher to assign the type of a polymorphic field in an existing struct instance.
package main
import (
"encoding/json"
"fmt"
"github.com/SoulKa/golymorph"
"github.com/mitchellh/mapstructure"
"reflect"
)
func main() {
// get a JSON that contains a payload with a type field that determines the type of the payload
alertEventJson := `{ "timestamp": "2023-11-27T22:14:09+00:00", "payload": { "type": "alert", "message": "something is broken!" } }`
type Event struct {
Timestamp string
Payload any
}
type AlertPayload struct {
Type string
Message string
}
type PingPayload struct {
Type string
Ip string
}
typeMap := golymorph.TypeMap{
"alert": reflect.TypeOf(AlertPayload{}),
"ping": reflect.TypeOf(PingPayload{}),
}
// parse the JSON into a map
var jsonMap map[string]any
if err := json.Unmarshal([]byte(alertEventJson), &jsonMap); err != nil {
panic(fmt.Sprintf("error unmarshalling JSON: %s", err))
}
// create a polymorpher that assigns the type of the payload based on the type field
err, polymorpher := golymorph.NewPolymorphismBuilder().
DefineTypeAt("payload").
UsingTypeMap(typeMap).
WithDiscriminatorAt("type").
Build()
if err != nil {
panic(fmt.Sprintf("error building polymorpher: %s", err))
}
// create a new event
var event Event
if err := polymorpher.AssignTargetType(&jsonMap, &event); err != nil {
panic(fmt.Sprintf("error assigning target type: %s", err))
}
// use mapstructure to unmarshal the payload into the event
if err := mapstructure.Decode(jsonMap, &event); err != nil {
panic(fmt.Sprintf("error decoding JSON map: %s", err))
}
// continue to work with the event
fmt.Printf("event: %+v\n", event)
fmt.Printf("event payload: %T %+v\n", event.Payload, event.Payload.(AlertPayload))
}
Output: event: {Timestamp:2023-11-27T22:14:09+00:00 Payload:{Type:alert Message:something is broken!}} event payload: golymorph_test.AlertPayload {Type:alert Message:something is broken!}
type TypeResolver ¶
type TypeResolver interface {
// AssignTargetType assigns the determined type to target based on the polymorphism rules. The matching rule with the
// highest priority is used. If no rule matches, the target type is not changed. The source and target must be pointers.
// If no matching type can be determined, an error.UnresolvedTypeError is returned.
AssignTargetType(source any, target any) error
}
TypeResolver is an interface that can resolve the type of a target based on the values of a source.