@@ -2,31 +2,56 @@ package cloudevent
22
33import (
44 "encoding/json"
5+ "fmt"
56 "reflect"
67 "strings"
78
89 "github.com/tidwall/sjson"
910)
1011
11- var definedCloudeEventHdrFields = getJSONFieldNames (reflect .TypeOf ( CloudEventHeader {} ))
12+ var definedCloudeEventHdrFields = getJSONFieldNames (reflect .TypeFor [ CloudEventHeader ]( ))
1213
1314type cloudEventHeader CloudEventHeader
1415
1516// UnmarshalJSON implements custom JSON unmarshaling for CloudEvent.
17+ // It transparently handles both "data" and "data_base64" wire formats.
1618func (c * CloudEvent [A ]) UnmarshalJSON (data []byte ) error {
17- var err error
18- c .CloudEventHeader , err = unmarshalCloudEvent (data , c .setDataField )
19- return err
19+ var dataRaw json.RawMessage
20+ var dataBase64 string
21+ header , err := unmarshalCloudEventWithPayload (data , func (d json.RawMessage , b64 string ) error {
22+ dataRaw = d
23+ dataBase64 = b64
24+ return nil
25+ })
26+ if err != nil {
27+ return err
28+ }
29+ c .CloudEventHeader = header
30+ if dataRaw != nil && dataBase64 != "" {
31+ return fmt .Errorf ("cloudevent: both \" data\" and \" data_base64\" present; only one allowed" )
32+ }
33+ if dataBase64 != "" {
34+ c .DataBase64 = dataBase64
35+ } else if dataRaw != nil {
36+ if err := json .Unmarshal (dataRaw , & c .Data ); err != nil {
37+ return err
38+ }
39+ }
40+ return nil
2041}
2142
22- // MarshalJSON implements custom JSON marshaling for CloudEventHeader.
43+ // MarshalJSON implements custom JSON marshaling for CloudEvent[A].
44+ // When DataBase64 is set, emits "data_base64"; otherwise emits "data".
2345func (c CloudEvent [A ]) MarshalJSON () ([]byte , error ) {
24- // Marshal the base struct
2546 data , err := json .Marshal (c .CloudEventHeader )
2647 if err != nil {
2748 return nil , err
2849 }
29- data , err = sjson .SetBytes (data , "data" , c .Data )
50+ if c .DataBase64 != "" {
51+ data , err = sjson .SetBytes (data , "data_base64" , c .DataBase64 )
52+ } else {
53+ data , err = sjson .SetBytes (data , "data" , c .Data )
54+ }
3055 if err != nil {
3156 return nil , err
3257 }
@@ -42,21 +67,18 @@ func (c *CloudEventHeader) UnmarshalJSON(data []byte) error {
4267
4368// MarshalJSON implements custom JSON marshaling for CloudEventHeader.
4469func (c CloudEventHeader ) MarshalJSON () ([]byte , error ) {
45- // Marshal the base struct
4670 aux := (cloudEventHeader )(c )
4771 aux .SpecVersion = SpecVersion
4872 data , err := json .Marshal (aux )
4973 if err != nil {
5074 return nil , err
5175 }
52- // Add all extras using sjson]
5376 for k , v := range c .Extras {
5477 data , err = sjson .SetBytes (data , k , v )
5578 if err != nil {
5679 return nil , err
5780 }
5881 }
59-
6082 return data , nil
6183}
6284
@@ -90,30 +112,48 @@ func getJSONFieldNames(t reflect.Type) map[string]struct{} {
90112
91113// unmarshalCloudEvent unmarshals the CloudEventHeader and data field.
92114func unmarshalCloudEvent (data []byte , dataFunc func (json.RawMessage ) error ) (CloudEventHeader , error ) {
93- c := CloudEventHeader {}
94- aux := cloudEventHeader {}
95- // Unmarshal known fields directly into the struct
96- if err := json .Unmarshal (data , & aux ); err != nil {
115+ return unmarshalCloudEventWithPayload (data , func (dataRaw json.RawMessage , _ string ) error {
116+ return dataFunc (dataRaw )
117+ })
118+ }
119+
120+ // unmarshalCloudEventWithPayload unmarshals the CloudEventHeader and returns both
121+ // "data" and "data_base64" for RawEvent.
122+ func unmarshalCloudEventWithPayload (data []byte , payloadFunc func (dataRaw json.RawMessage , dataBase64 string ) error ) (CloudEventHeader , error ) {
123+ // Unmarshal known header fields via the type alias (no custom UnmarshalJSON).
124+ var c CloudEventHeader
125+ if err := json .Unmarshal (data , (* cloudEventHeader )(& c )); err != nil {
97126 return c , err
98127 }
99- aux .SpecVersion = SpecVersion
100- c = ( CloudEventHeader )( aux )
101- // Create a map to hold all JSON fields
128+ c .SpecVersion = SpecVersion
129+
130+ // Second pass into raw map to extract data, data_base64, and extras.
102131 rawFields := make (map [string ]json.RawMessage )
103132 if err := json .Unmarshal (data , & rawFields ); err != nil {
104133 return c , err
105134 }
106135
107- // Separate known and unknown fields
136+ var dataRaw json.RawMessage
137+ var dataBase64 string
138+ if raw , ok := rawFields ["data_base64" ]; ok && len (raw ) > 0 {
139+ if err := json .Unmarshal (raw , & dataBase64 ); err != nil {
140+ return c , err
141+ }
142+ }
143+ if raw , ok := rawFields ["data" ]; ok {
144+ dataRaw = raw
145+ }
146+ if dataRaw != nil || dataBase64 != "" {
147+ if err := payloadFunc (dataRaw , dataBase64 ); err != nil {
148+ return c , err
149+ }
150+ }
151+
108152 for key , rawValue := range rawFields {
109153 if _ , ok := definedCloudeEventHdrFields [key ]; ok {
110- // Skip defined fields
111154 continue
112155 }
113- if key == "data" {
114- if err := dataFunc (rawValue ); err != nil {
115- return c , err
116- }
156+ if key == "data" || key == "data_base64" {
117157 continue
118158 }
119159 if c .Extras == nil {
@@ -131,9 +171,3 @@ func unmarshalCloudEvent(data []byte, dataFunc func(json.RawMessage) error) (Clo
131171// ignoreDataField is a function that ignores the data field.
132172// It is used when unmarshalling the CloudEventHeader so that the data field is not added to the Extras map.
133173func ignoreDataField (json.RawMessage ) error { return nil }
134-
135- // setDataField is a function that sets the data field.
136- // It is used to unmarshal the data field into the CloudEvent[A].Data field.
137- func (c * CloudEvent [A ]) setDataField (data json.RawMessage ) error {
138- return json .Unmarshal (data , & c .Data )
139- }
0 commit comments