将 JSON 数据解组到 Go 结构中可能是一项简单的任务。但是,在处理包含动态数据结构的 JSON 文档时,字段的类型可能会有所不同,因此该过程可能会变得更加复杂。本文探讨了解决此挑战的方法,而不引入通用占位符字段。
考虑以下 JSON 规范:
{ "some_data": "foo", "dynamic_field": { "type": "A", "name": "Johnny" }, "other_data": "bar" }
{ "some_data": "foo", "dynamic_field": { "type": "B", "address": "Somewhere" }, "other_data": "bar" }
两个 JSON 文档都应该被解组到同一个 Go 结构中:
type BigStruct struct { SomeData string `json:"some_data"` DynamicField Something `json:"dynamic_field"` OtherData string `json:"other_data"` }
关键问题是:如何创建 Something 类型并实现解组逻辑?
解决方案涉及为 Something 类型创建接口:
type Something interface { GetType() string }
接下来,定义实现 Something 接口的特定结构类型:
type BaseDynamicType struct { Type string `json:"type"` } type DynamicTypeA struct { BaseDynamicType Name string `json:"name"` } type DynamicTypeB struct { BaseDynamicType Address string `json:"address"` }
The DynamicType 接口方法允许将 JSON 数据解组为适当的结构:
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) }
此方法检查 JSON 数据并根据需要创建 TypeA 或 TypeB 的实例。
最后,在 BigStruct 上实现 UnmarshalJSON 方法type:
func (b *BigStruct) UnmarshalJSON(data []byte) error { var tmp BigStruct // avoids infinite recursion return json.Unmarshal(data, &tmp) }
此方法使用临时 BigStruct 类型来避免递归,并允许根据 JSON 数据中的类型字段使用适当的 DynamicType 类型对动态字段进行解组。
该解决方案提供了一种干净有效的方法来解组动态 JSON 数据,而不需要额外的通用占位符字段。通过使用接口并实现自定义 UnmarshalJSON 方法,Go 结构体可以适应 JSON 输入中的动态数据结构。
以上是如何在没有通用占位符字段的情况下在 Go 中解组动态 JSON?的详细内容。更多信息请关注PHP中文网其他相关文章!