Unmarshal Dynamic JSON Based on a Type Key
Unmarshaling complex JSON data into a Go struct can be challenging when the JSON structure contains dynamic fields of varying types. This article addresses a specific scenario where the JSON fields hold mostly simple values, but occasionally a dynamic field with a specific type key determines the type of the field's value.
The goal is to create a Go struct with the same structure as the provided JSON, where the dynamic field is represented as an interface type, allowing for flexible handling based on its type.
One possible solution utilizes the following custom types:
type BigStruct struct { SomeData string `json:"some_data"` DynamicField Something `json:"dynamic_field"` OtherData string `json:"other_data"` } type Something interface { GetType() string }
Then, create individual structs for each dynamic field type:
type BaseDynamicType struct { Type string `json:"type"` } type DynamicTypeA struct { BaseDynamicType Name string `json:"name"` } type DynamicTypeB struct { BaseDynamicType Address string `json:"address"` } func (d *BaseDynamicType) GetType() string { return d.Type }
To unmarshal the JSON into this struct, the BigStruct can implement a custom UnmarshalJSON method:
func (b *BigStruct) UnmarshalJSON(data []byte) error { var tmp struct { SomeData string `json:"some_data"` DynamicField json.RawMessage `json:"dynamic_field"` OtherData string `json:"other_data"` } if err := json.Unmarshal(data, &tmp); err != nil { return err } b.Unmarshal(tmp.DynamicField) return nil }
The Unmarshal method can be called from within UnmarshalJSON to parse the dynamic field:
func (b *BigStruct) Unmarshal(data json.RawMessage) error { switch UnmarshalledType(data) { case "A": var a DynamicTypeA if err := json.Unmarshal(data, &a); err != nil { return err } b.DynamicField = &a case "B": var b DynamicTypeB if err := json.Unmarshal(data, &b); err != nil { return err } b.DynamicField = &b } return nil } func UnmarshalledType(b json.RawMessage) string { var typ struct { Type string `json:"type"` } if err := json.Unmarshal(b, &typ); err != nil { log.Fatalf("Error extracting type from RawMessage: %v", err) } return typ.Type }
With this approach, you can unmarshal dynamic JSON fields into the Go struct without introducing an additional placeholder field.
The above is the detailed content of How to Unmarshal Dynamic JSON Fields in Go Based on a Type Key?. For more information, please follow other related articles on the PHP Chinese website!