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

在 Go 中序列化混合类型的 JSON 数组

在 Go 中序列化混合类型的 JSON 数组

Go
慕尼黑8549860 2021-09-10 21:43:40
我想返回一个如下所示的结构:{    results: [        ["ooid1", 2.0, "Söme text"],        ["ooid2", 1.3, "Åther text"],    ]}这是一个字符串数组,浮点数,unicode 字符。如果是 Python,我将能够:import jsonjson.dumps({'results': [["ooid1", 2.0, u"Söme text"], ...])但是在 Go 中,您不能拥有混合类型的数组(或切片)。我想过使用这样的结构:type Row struct {    Ooid string    Score float64    Text rune}但我不希望每个都成为字典,我希望它成为每个包含 3 个元素的数组。
查看完整描述

3 回答

?
江户川乱折腾

TA贡献1851条经验 获得超5个赞

我们可以通过实现json.Marshaler接口来自定义对象的序列化方式。对于我们的特殊情况,我们似乎有一个Row元素切片,我们希望将其编码为一个异构值数组。我们可以通过MarshalJSON在我们的Row类型上定义一个函数来做到这一点,使用中间切片interface{}对混合值进行编码。


这个例子演示了:


package main


import (

    "encoding/json"

    "fmt"

)


type Row struct {

    Ooid  string

    Score float64

    Text  string

}


func (r *Row) MarshalJSON() ([]byte, error) {

    arr := []interface{}{r.Ooid, r.Score, r.Text}

    return json.Marshal(arr)

}


func main() {

    rows := []Row{

        {"ooid1", 2.0, "Söme text"},

        {"ooid2", 1.3, "Åther text"},

    }

    marshalled, _ := json.Marshal(rows)

    fmt.Println(string(marshalled))

}

当然,我们也可能想反过来,从 JSON 字节回到结构体。所以我们可以使用一个类似的json.Unmarshaler接口。


func (r *Row) UnmarshalJSON(bs []byte) error {

    arr := []interface{}{}

    json.Unmarshal(bs, &arr)

    // TODO: add error handling here.

    r.Ooid = arr[0].(string)

    r.Score = arr[1].(float64)

    r.Text = arr[2].(string)

    return nil

}

这使用了类似的技巧,首先使用 的中间切片interface{},使用解组器将值放入这个通用容器中,然后将值放回我们的结构中。


package main


import (

    "encoding/json"

    "fmt"

)


type Row struct {

    Ooid  string

    Score float64

    Text  string

}


func (r *Row) UnmarshalJSON(bs []byte) error {

    arr := []interface{}{}

    json.Unmarshal(bs, &arr)

    // TODO: add error handling here.

    r.Ooid = arr[0].(string)

    r.Score = arr[1].(float64)

    r.Text = arr[2].(string)

    return nil

}


func main() {

    rows := []Row{}

    text := `

    [

          ["ooid4", 3.1415, "pi"],

          ["ooid5", 2.7182, "euler"]

        ]

    `

    json.Unmarshal([]byte(text), &rows)

    fmt.Println(rows)

}

您可以在此处阅读完整示例。


查看完整回答
反对 回复 2021-09-10
?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

用 []interface{}


type Results struct {

     Rows []interface{} `json:"results"`

}

如果要访问存储在中的值,则必须使用类型断言 []interface{}


for _, row := range results.Rows {

    switch r := row.(type) {

    case string:

        fmt.Println("string", r)

    case float64:

        fmt.Println("float64", r)

    case int64:

        fmt.Println("int64", r)

    default:

        fmt.Println("not found")

    } 

}


查看完整回答
反对 回复 2021-09-10
  • 3 回答
  • 0 关注
  • 252 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信