首页 >后端开发 >Golang >如何在 Go 中有效地解组不一致的 JSON 字段(有时是字符串,有时是字符串数组)?

如何在 Go 中有效地解组不一致的 JSON 字段(有时是字符串,有时是字符串数组)?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-12-22 01:21:15452浏览

How Can I Efficiently Unmarshal Inconsistent JSON Fields That Are Sometimes Strings and Sometimes Arrays of Strings in Go?

不一致的 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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn