不一致的 JSON 字段处理:解组为字符串或数组
使用表现出不一致的 JSON 数据时,解组可能具有挑战性类型可以不同的字段,例如字符串或字符串数组。本文解决了这个问题并提供了实用的解决方案。
问题
考虑以下 JSON 结构,其中“display_name”字段是字符串或字符串数组:
{ "date": "30 Apr", "display_name": "Mr Smith" }, { "date": "30 Apr", "display_name": ["Mr Smith", "Mr Jones"], }
尝试使用以下 Go 结构解组此数据将导致错误:
type MyListItem struct { Date string `json:"date"` DisplayName string `json:"display_name"` } type MyListings struct { CLItems []MyListItem `json:"myitems"` }
解决方案
要克服这一挑战,可以利用 json.RawMessage 的多功能性,它允许捕获不同的字段数据。此外,“-”字段名称可用于对解码器隐藏“DisplayName”字段,允许应用程序在解码顶级 JSON 后填充该字段。
修改的 Go 结构
type MyListItem struct { Date string `json:"date"` RawDisplayName json.RawMessage `json:"display_name"` DisplayName []string `json:"-"` }
解组处理
解组顶级JSON:
var li MyListItem if err := json.Unmarshal(data, &li); err != nil { // handle error }
根据原始数据的类型重建“display_name”字段:
if len(li.RawDisplayName) > 0 { switch li.RawDisplayName[0] { case '"': if err := json.Unmarshal(li.RawDisplayName, &li.DisplayName); err != nil { // handle error } case '[': var s []string if err := json.Unmarshal(li.RawDisplayName, &s); err != nil { // handle error } // Join arrays with "&&" per OP's comment on the question. li.DisplayName = strings.Join(s, "&&") } }
对于如果数据模型中多次出现这种不一致的字段,可以使用 json.Unmarshaler 接口的自定义类型和实现来封装
自定义解组器
type multiString string func (ms *multiString) UnmarshalJSON(data []byte) error { if len(data) > 0 { switch data[0] { case '"': var s string if err := json.Unmarshal(data, &s); err != nil { return err } *ms = multiString(s) case '[': var s []string if err := json.Unmarshal(data, &s); err != nil { return err } *ms = multiString(strings.Join(s, "&&")) } } return nil }
与自定义解组器一起使用
type MyListItem struct { Date string `json:"date"` DisplayName multiString `json:"display_name"` } type MyListings struct { CLItems []MyListItem `json:"myitems"` } var listings MyListings if err := json.Unmarshal([]byte(data), &listings); err != nil { log.Fatal(err) }
这些解决方案提供了全面的有效处理不一致的 JSON 字段的方法,允许数据结构和 JSON 之间的灵活映射表示。
以上是如何在 Go 中有效地解组不一致的 JSON 字段(有时是字符串,有时是字符串数组)?的详细内容。更多信息请关注PHP中文网其他相关文章!