【问题标题】:How to Unmarshall data to JSON with unknown field types如何将数据解组为具有未知字段类型的 JSON
【发布时间】:2021-05-09 08:47:03
【问题描述】:

我有这些“结构”

type Results struct {
    Gender string `json:"gender"`
    Name   struct {
        First string `json:"first"`
        Last  string `json:"last"`
    } `json:"name"`
    Location struct {
        Postcode int `json:"postcode"`
    }
    Registered struct {
        Date string `json:"date"`
    } `json:"registered"`
}

type Info struct {
    Seed    string `json:"seed"`
    Results int64  `json:"results"`
    Page    int64  `json:"page"`
    Version string `json:"version"`
}

type Response struct {
    Results []Results `json:"results"`
    Info    Info      `json:"info"`
}

我向外部 API 发出请求并将数据转换为 JSON 视图。 我事先知道所有字段的类型,但是“邮政编码”字段出现问题。我得到不同类型的值,这就是我得到 JSON 解码错误的原因。 在这种情况下,“邮政编码”可以是以下三种变体之一:

  1. 字符串~“13353”
  2. int ~ 13353
  3. 字符串~“13353邮政编码”

postcode 类型从string 更改为json.Number 解决了这个问题。 但是这个方案不满足第三个“选项”。

我知道我可以尝试创建自定义类型并在其上实现接口。在我看来,使用json.RawMessage 是最好的解决方案。这是我第一次遇到这个问题,所以我仍在寻找解决方案的实现并阅读文档。

在这种情况下,最好的解决方案是什么? 提前致谢。

【问题讨论】:

    标签: json api go unmarshalling


    【解决方案1】:

    声明一个自定义字符串类型并让它实现json.Unmarshaler 接口。

    例如,您可以这样做:

    type PostCodeString string
    
    // UnmarshalJSON implements the json.Unmarshaler interface.
    func (s *PostCodeString) UnmarshalJSON(data []byte) error {
        if data[0] != '"' { // not string, so probably int, make it a string by wrapping it in double quotes
            data = []byte(`"`+string(data)+`"`)
        }
    
        // unmarshal as plain string
        return json.Unmarshal(data, (*string)(s))
    }
    

    https://play.golang.org/p/pp-zNNWY38M

    【讨论】:

    • 这是一个很好的解决方案,但我没有从 API 获取字符串数组。示例响应(对不起,如果 cmets 可读性差):{ "results": [ { "name": { "first": "Aurélien", "last": "Andre" }, "location": { "postcode": 58499 } }, { "name": { "first": "Endre", "last": "Gjerdrum" }, "location": { "postcode": "5018" } }, { "name": { "first": "Dwight", "last": "Johnson" }, "location": { "postcode": "IM33 4LY" } } ], "info": { "seed": "320731c5fddfed33", "results": 3, "page": 1, "version": "1.3" } } 因此,我不太了解如何在我的情况下使用您的解决方案。
    • 这只是证明解决方案可以处理所有 3 种类型(整数、带整数的字符串、带文本的字符串)的示例。您已经知道如何将string 更改为json.Number,现在做同样的事情,但不要将string 更改为json.Number,而是将其更改为PostCodeString
    猜你喜欢
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 2022-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多