为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
www说 2022-06-27 15:20:33
我正在编写一个简单的应用程序,它向返回类型的异构 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 mainimport (    "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最后,这是我目前 在 Golang an Introduction 中实现所需的 GO 结构 JSON方法的灵感。
查看完整描述

1 回答

?
千万里不及你

TA贡献1784条经验 获得超9个赞

类型 ResArray 结构 {


但它不是结构,而是切片!


type LastArray struct {

    Info string

}

但它不是字符串,有时是字符串,有时是数字。


执行此操作的简单方法是将您的类型定义为


type Equipment struct {

    Results [][]interface{}

}

它说结果包含一片……某物。您可以命名中间类型,但这不是必需的。那么例如e.Results[0][1].(string)将是"Zho's Mask"。


更好的方法是通过提供一个 custom来实现UnmarshalerUnmarshalJSON接口,如下所示:


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 请求的确切字段列表结合在一起——如果您更改它,您将不得不更改类型和从数组加载它的解组函数。


查看完整回答
反对 回复 2022-06-27
  • 1 回答
  • 0 关注
  • 249 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号