json - 在 GO 中反序列化一个非标准的 json

标签 json go deserialization

我正在编写一个简单的应用程序,它向返回类型的异构 JSON 的 API 发出请求

{
  "results": [
    [123, "Zho's Mask", 10586],
    [345, "Ravaging Superior Studded Coat", 58]
  ]
}
最终,我希望能够使用结果响应中的特定索引。例如,我希望能够获得“Zho's Mask”,或者价格:10586。这是我正在使用的 API GW2TP .
GO JSON 博客中的大多数示例都引用了不包含嵌套数组的更简单或直接的 JSON。
根据我的阅读,由于我知道 JSON 响应的一般外观,我可以制作一个 GO 结构并将其解码为该结构的一个实例。但是,我无法为这项工作创建正确的结构。
这是我目前创建适当结构的尝试
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

// {"results":[[123,"Zho's Mask",3532]]}

type Equipment struct {
    Results []ResArray
}

type ResArray struct {
    Medium []LastArray
}

type LastArray struct {
    Info string
}

func main() {
    res, err := http.Get("http://api.gw2tp.com/1/items?ids=123&fields=name,sell")
    if err != nil {
        log.Fatal(err)
    }

    var equipment Equipment

    data, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Print("ReadAll Error: ", err, "\n")
    }
    err = json.Unmarshal(data, &equipment)
    if err != nil {
        fmt.Print("Unmarshal error: ", err, "\n")
    }

}
这是解码错误:
Unmarshal error: json: cannot unmarshal array into Go struct field Equipment.Results of type main.ResArray
最后,这是我目前对这个所需的 GO 结构的方法的灵感
JSON in Golang an Introduction .

最佳答案

type ResArray struct {


但它不是结构,而是 slice !
type LastArray struct {
    Info string
}

但它不是字符串,有时是字符串,有时是数字。
执行此操作的简单方法是将您的类型定义为
type Equipment struct {
    Results [][]interface{}
}
它说结果包含一片……某物。您可以命名中间类型,但这不是必需的。然后例如e.Results[0][1].(string)将是 "Zho's Mask" .
更好的方法是实现 Unmarshaler通过提供自定义接口(interface)UnmarshalJSON ,像这样:
type Equipment struct {
    Results []Item
}

type Item struct {
    ID int
    Name string
    Sell int
}

func (i *Item) UnmarshalJSON(b []byte) error {
    // We're deserializing into a struct, but in JSON it's a mixed-type array.
    var arr []interface{}
    err := json.Unmarshal(b, &arr)
    if err != nil {
        return fmt.Errorf("unmarshal Item underlying array: %w", err)
    }
    if len(arr) != 3 {
        return fmt.Errorf("Item underlying array should be 3 elements, got %d", len(arr))
    }

    // JSON numbers will become float64 when loaded into interface{} but we want int
    id, ok := arr[0].(float64)
    if !ok {
        return fmt.Errorf("expected float64 for Item.ID, got %T", arr[0])
    }
    i.ID = int(id)

    i.Name, ok = arr[1].(string)
    if !ok {
        return fmt.Errorf("expected string for Item.Name, got %T", arr[1])

    }

    sell, ok := arr[2].(float64)
    if !ok {
        return fmt.Errorf("expected float64 for Item.Sell, got %T", arr[2])
    }
    i.Sell = int(sell)
    return nil
}
请记住,这些类型与您向 API 请求的确切字段列表结合在一起——如果您更改它,您将不得不更改类型和从数组加载它的解码函数。

关于json - 在 GO 中反序列化一个非标准的 json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63675435/

相关文章:

javascript - 在迭代期间向 JSON 对象添加属性?

json - 获取请求状态代码 : 400 Swift

go - 如何从 gitlab 子组加载模块?

c# - 使用 BinaryFormatter 反序列化加密数据时出现问题

javascript - 如何将 json POST 到 Wufoo Entries API?

json数据中可以写注释吗?

google-app-engine - 戈朗 : emailing an image stored as a Google Appengine blobstore blob

python - 在 Go 中解密在 Python 中以 CFB 模式使用 AES 加密的内容

java - 在顶级 map 上使用@JacksonInject 和@JsonCreator

c++ - Qt Override class properties on control deserealization