-
Notifications
You must be signed in to change notification settings - Fork 0
/
example_test.go
125 lines (103 loc) · 3.75 KB
/
example_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package golymorph_test
import (
"encoding/json"
"fmt"
"github.com/SoulKa/golymorph"
"github.com/mitchellh/mapstructure"
"reflect"
)
// ExampleUnmarshalJSON demonstrates how to use the polymorpher to unmarshal a JSON into a struct with a polymorphic field.
func ExampleUnmarshalJSON() {
// 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!}
}
// ExampleTypeMapPolymorphism_AssignTargetType demonstrates how to use the polymorpher to assign the
// type of a polymorphic field in an existing struct instance.
func ExampleTypeMapPolymorphism_AssignTargetType() {
// 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!}
}