在 Go 中解组顶级 JSON 数组

我正在通过编写一个简单的 http 服务器来学习 Go,我需要处理一些 JSON 响应。


使用对象响应,我可以用 2 行代码惯用地解组它: structResult := Foo{} json.Unmarshal(structBody, &structResult)


我不知道如何对数组响应执行相同的操作(请参见下面的示例)。有没有办法指定(可能通过 json 标签)顶级数组应该进入给定的结构字段?


package main


import "fmt"

import "encoding/json"


type Foo struct {

    Id uint64 `json:"id"`

    Name string `json:"name"`

}


type BaseResult struct {

    Error string  `json:"error"`

}


type FooResult struct {

    BaseResult

    Foos []Foo

}


func main() {

    // Simple and works.

    structBody := []byte(`{"id": 1,"name": "foo"}`)

    structResult := Foo{}

    json.Unmarshal(structBody, &structResult)

    fmt.Printf("%#v\n", structResult)


    // Doesn't work.

    arrayBody := []byte(`[{"id": 1,"name": "foo"},{"id": 2,"name": "bar"},{"id": 3,"name": "foobar"}]`) 

    arrayResult := FooResult{}

    json.Unmarshal(arrayBody, &arrayResult)

    fmt.Printf("%#v\n", arrayResult)

}

我知道我可以让 FooResult 成为一个数组:


type FooResult []Foo

但后来我失去了指定基础对象的能力,我想用它来存储错误消息等。我也知道我可以直接解组到 &fooResult.Foos 中,但我希望代码能够同时处理对象和数组。


更新


按照@dyoo 的建议实现 UnmarshalJSON 部分解决了我的问题,但我希望我可以使用 BaseResult 来存储解析错误,以防 JSON 具有不同的结构:


arrayBody := []byte(`{"error": "foo"}`)

arrayResult := FooResult{}

json.Unmarshal(arrayBody, &arrayResult)

fmt.Printf("%#v\n", arrayResult)

当然,我可以在 UnmarshalJSON 中实现更复杂的逻辑 - 但没有更简单的方法来做到这一点吗?


人到中年有点甜
浏览 223回答 2
2回答

qq_遁去的一_1

只需指定Foos何时解组package mainimport "fmt"import "encoding/json"type Foo struct {    Id   uint64 `json:"id"`    Name string `json:"name"`}type BaseResult struct {    Error string `json:"error"`}type FooResult struct {    BaseResult    Foos []Foo}func main() {    // Simple and works.    structBody := []byte(`{"id": 1,"name": "foo"}`)    structResult := Foo{}    json.Unmarshal(structBody, &structResult)    fmt.Printf("%#v\n", structResult)    // Doesn't work.    arrayBody := []byte(`[{"id": 1,"name": "foo"},{"id": 2,"name": "bar"},{"id": 3,"name": "foobar"}]`)    arrayResult := FooResult{}    if err := json.Unmarshal(arrayBody, &arrayResult.Foos); err != nil {        arrayResult.BaseResult.Error = string(arrayBody)    }    fmt.Printf("%#v\n", arrayResult)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go