@@ -63,20 +63,96 @@ const (
6363)
6464
6565type Message struct {
66- Cursor string `json:"__cursor"`
67- ID string `json:"id"`
68- ChannelID string `json:"channel_id"`
69- Recipient string `json:"recipient"`
70- Workflow string `json:"workflow"`
71- Tenant string `json:"tenant"`
72- Status EngagementStatus `json:"status"`
73- ReadAt time.Time `json:"read_at"`
74- SeenAt time.Time `json:"seen_at"`
75- ArchivedAt time.Time `json:"archived_at"`
76- InsertedAt time.Time `json:"inserted_at"`
77- UpdatedAt time.Time `json:"updated_at"`
78- Source * NotificationSource `json:"source"`
79- Data map [string ]interface {} `json:"data"`
66+ Cursor string
67+ ID string
68+ ChannelID string
69+ Workflow string
70+ Tenant string
71+ Status EngagementStatus
72+ ReadAt time.Time
73+ SeenAt time.Time
74+ ArchivedAt time.Time
75+ InsertedAt time.Time
76+ UpdatedAt time.Time
77+ Source * NotificationSource
78+ Data map [string ]interface {}
79+
80+ // If the message recipient is an object, ObjectRecipient will be non-nil
81+ // and Recipient will be an empty string. Otherwise, ObjectRecipient will be nil
82+ // and the Recipient string will be non-empty.
83+ ObjectRecipient * ObjectRecipient
84+ Recipient string
85+ }
86+
87+ // The Knock Message json schema has a polymorphic type for the `recipient` field.
88+ // It can hold either a string value or a json object. In order to avoid an `interface{}`
89+ // type for Message.Recipient we use a custom unmarshaller.
90+ func (m * Message ) UnmarshalJSON (b []byte ) error {
91+ var msg struct {
92+ RawRecipient json.RawMessage `json:"recipient"`
93+
94+ Cursor string `json:"__cursor"`
95+ ID string `json:"id"`
96+ ChannelID string `json:"channel_id"`
97+ Workflow string `json:"workflow"`
98+ Tenant string `json:"tenant"`
99+ Status EngagementStatus `json:"status"`
100+ ReadAt time.Time `json:"read_at"`
101+ SeenAt time.Time `json:"seen_at"`
102+ ArchivedAt time.Time `json:"archived_at"`
103+ InsertedAt time.Time `json:"inserted_at"`
104+ UpdatedAt time.Time `json:"updated_at"`
105+ Source * NotificationSource `json:"source"`
106+ Data map [string ]interface {} `json:"data"`
107+ }
108+
109+ err := json .Unmarshal (b , & msg )
110+ if err != nil {
111+ return err
112+ }
113+
114+ // these fields have known types
115+ m .Cursor = msg .Cursor
116+ m .ID = msg .ID
117+ m .ChannelID = msg .ChannelID
118+ m .Workflow = msg .Workflow
119+ m .Tenant = msg .Tenant
120+ m .Status = msg .Status
121+ m .ReadAt = msg .ReadAt
122+ m .SeenAt = msg .SeenAt
123+ m .ArchivedAt = msg .ArchivedAt
124+ m .InsertedAt = msg .InsertedAt
125+ m .UpdatedAt = msg .UpdatedAt
126+ m .Source = msg .Source
127+ m .Data = msg .Data
128+
129+ // first, attempt to parse the `recipient` field value into a string
130+ var stringRecip string
131+ err = json .Unmarshal (msg .RawRecipient , & stringRecip )
132+ if err != nil {
133+ if _ , ok := err .(* json.UnmarshalTypeError ); ok {
134+ // if we can't parse into a string, attempt to parse into an object
135+ var objectRecip ObjectRecipient
136+ err = json .Unmarshal (msg .RawRecipient , & objectRecip )
137+ if err != nil {
138+ return err
139+ }
140+
141+ // if we succesfully parse `recipient` into an object, set Message.ObjectRecipient
142+ m .ObjectRecipient = & objectRecip
143+ return nil
144+ }
145+ return err
146+ }
147+
148+ // if we succesfully parse `recipient` into a string, set Message.Recipient
149+ m .Recipient = stringRecip
150+ return nil
151+ }
152+
153+ type ObjectRecipient struct {
154+ Id string `json:"id"`
155+ Collection string `json:"collection"`
80156}
81157
82158type NotificationSource struct {
0 commit comments