Unmarshaling Dynamic JSON Based on a Type Key Without Introducing Generic Fields
Many structured JSON data require unmarshalling into Go structs, often containing nested fields with varying data types. When a nested field's data type varies based on a type key within the JSON, conventional methods of unmarshalling using custom fields can lead to unnecessary boilerplate code.
In this context, let's consider the following JSON spec:
{ "some_data": "foo", "dynamic_field": { "type": "A", "name": "Johnny" }, "other_data": "bar" }
and
{ "some_data": "foo", "dynamic_field": { "type": "B", "address": "Somewhere" }, "other_data": "bar" }
Both these JSON documents should be unmarshalled into the same Go struct:
type BigStruct struct { SomeData string `json:"some_data"` DynamicField Something `json:"dynamic_field"` OtherData string `json:"other_data"` }
The challenge lies in defining the 'Something' type that can accommodate dynamic data based on the 'type' key within the 'dynamic_field' object.
To avoid the need for an explicit 'generic' field (e.g., Value, Data), we can leverage the power of type embedding and interfaces.
type BigStruct struct { SomeData string `json:"some_data"` DynamicField DynamicType `json:"dynamic_field"` OtherData string `json:"other_data"` } type DynamicType struct { Value interface{} }
Within the 'DynamicType,' the 'Value' field can hold any type of data, based on the 'type' key in the JSON. To facilitate proper unmarshalling, we implement the UnmarshalJSON method on the '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(TypeA) case "B": d.Value = new(TypeB) } return json.Unmarshal(data, d.Value) }
We define specific types for different types of data:
type TypeA struct { Name string `json:"name"` } type TypeB struct { Address string `json:"address"` }
With this approach, we can unmarshal the JSON documents without the need for an additional generic field, allowing us to maintain a clean and extensible data structure.
The above is the detailed content of How to Unmarshal Dynamic JSON in Go Based on a Type Key Without Generic Fields?. For more information, please follow other related articles on the PHP Chinese website!