Unmarshaling Dynamic JSON with an Embedded Type Key
In Go, unmarshaling JSON data into a struct with a field of a dynamic type can be challenging. This article explores a solution that leverages custom structs and an embedded type key to achieve this.
Problem Statement
Consider the following JSON structure:
{ "some_data": "foo", "dynamic_field": { "type": "A", "name": "Johnny" }, "other_data": "bar" }
We want to unmarshal this JSON into a Go struct that has a field DynamicField of an interface type Something. Depending on the value of the type key in the JSON, DynamicField should correspond to either DynamicTypeA or DynamicTypeB.
Solution
To solve this problem, we define the following custom structs:
type Something interface { GetType() string } type DynamicType struct { Type string `json:"type"` Value interface{} `json:"-"` // Not exported }
DynamicType represents the dynamic field, with the Type key embedded to determine the actual type of the data. The Value field is not exported to prevent direct access.
Next, we define the Go struct to represent the JSON:
type BigStruct struct { SomeData string `json:"some_data"` DynamicField DynamicType `json:"dynamic_field"` OtherData string `json:"other_data"` }
Finally, we implement the UnmarshalJSON method for DynamicType:
func (d *DynamicType) UnmarshalJSON(data []byte) error { var typ struct { Type string `json:"type"` } if err := json.Unmarshal(data, &typ); err != nil { return err } switch typ.Type { case "A": d.Value = new(DynamicTypeA) case "B": d.Value = new(DynamicTypeB) } return json.Unmarshal(data, d.Value) }
This method unmarshals the type key and then creates an appropriate struct (DynamicTypeA or DynamicTypeB) based on the value. It then unmarshals the remaining JSON data into the created struct, which is then stored in the Value field.
The above is the detailed content of How to Unmarshal Dynamic JSON with an Embedded Type Key in Go?. For more information, please follow other related articles on the PHP Chinese website!