-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathexample_structs_test.go
More file actions
105 lines (88 loc) · 2.55 KB
/
example_structs_test.go
File metadata and controls
105 lines (88 loc) · 2.55 KB
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
package jsondiscrim_test
import (
"fmt"
"github.com/go-json-experiment/json"
"github.com/cue-exp/jsondiscrim"
)
// Message is the interface type that all message types implement.
type Message interface {
Format() string
}
// BaseMessage encapsulates the discriminator field part of the
// [Message] type. Its type parameter must hold the "const" type
// parameter as expected by [jsondiscrim.Const], defining the
// discriminator value.
type BaseMessage[S any] struct {
Type jsondiscrim.Const[string, S] `json:"type"`
}
// TextMessage represents a text message.
type TextMessage struct {
BaseMessage[struct {
string `const:"text"`
}]
Text string `json:"text"`
}
func (m *TextMessage) Format() string {
return fmt.Sprintf("Text: %s", m.Text)
}
// ImageMessage represents an image message.
type ImageMessage struct {
BaseMessage[struct {
string `const:"image"`
}]
URL string `json:"url"`
Alt string `json:"alt"`
}
func (m *ImageMessage) Format() string {
return fmt.Sprintf("Image: %s (%s)", m.URL, m.Alt)
}
// LinkMessage represents a link message.
type LinkMessage struct {
BaseMessage[struct {
string `const:"link"`
}]
URL string `json:"url"`
Text string `json:"text"`
}
func (m *LinkMessage) Format() string {
return fmt.Sprintf("Link: %s -> %s", m.Text, m.URL)
}
// Conversation represents a collection of messages.
type Conversation struct {
Messages []Message `json:"messages"`
}
// This example demonstrates how to use Structs to unmarshal JSON
// with a discriminator field into different concrete types based
// on the discriminator value.
func Example_structs() {
// Create an unmarshaler for the Message interface.
unmarshalers := jsondiscrim.Structs[Message](
(*TextMessage)(nil),
(*ImageMessage)(nil),
(*LinkMessage)(nil),
)
// Example JSON conversation with mixed message types.
conversationJSON := `{
"messages": [
{"type":"text","text":"Hello, World!"},
{"type":"image","url":"https://example.com/pic.jpg","alt":"A picture"},
{"type":"link","url":"https://example.com","text":"Visit our site"},
{"type":"text","text":"Goodbye!"}
]
}`
// Unmarshal the entire conversation.
var conv Conversation
if err := json.Unmarshal([]byte(conversationJSON), &conv, json.WithUnmarshalers(unmarshalers)); err != nil {
fmt.Printf("Error: %v\n", err)
return
}
// Print each message using its Format method.
for _, msg := range conv.Messages {
fmt.Println(msg.Format())
}
// Output:
// Text: Hello, World!
// Image: https://example.com/pic.jpg (A picture)
// Link: Visit our site -> https://example.com
// Text: Goodbye!
}