4

我需要以灵活的方式指定用于解码 JSON 数据的类型,这意味着需要在运行时指定类型。

考虑这个片段:http ://play.golang.org/p/F-Jy4ufMPz

s := `{"b":[{"x":9},{"x":4}]}`

var a struct {
  B []interface{}
}
err := json.Unmarshal([]byte(s), &a)
if err != nil {
  panic(err)
}

fmt.Println(a)

这将产生{[map[x:9] map[x:4]]}. 我想解码为特定(结构)类型的数组,而不是[]interface{}在编译时指定它。

如果不预先创建数组,这是否可能?(退货数量未知)

我现在能想到的唯一方法是稍后再次对返回的地图进行编码,并将它们解码为指定的类型,这会产生不必要的处理开销。

4

1 回答 1

5

如果在编译时没有指定它,你仍然需要在某个地方指定它。

如果在检索 Json 数据之前指定,您可以简单地做一个 switch case,将其解组到您想要的对象。

如果json.RawMessageJson 数据中指定,您可以在确定适合的结构类型后将“灵活”部分编组到 a中进行处理:

package main

import (
    "encoding/json"
    "fmt"
)

var s = `{"type":"structx", "data":{"x":9,"xstring":"This is structX"}}`

type JsonStruct struct {
    Type string
    Data json.RawMessage
}

type StructX struct {
    X       float64
    Xstring string
}

type StructY struct {
    Y bool
}

func main() {
    var a *JsonStruct
    err := json.Unmarshal([]byte(s), &a)
    if err != nil {
        panic(err)
    }

    switch a.Type {
    case "structx":
        // We Unmashal the RawMessage part into a StructX
        var s *StructX
        json.Unmarshal([]byte(a.Data), &s)
        if err != nil {
            panic(err)
        }
        fmt.Println(s)
    case "structy":
        // Do the same but for structY
    }
}

操场

于 2013-10-30T20:19:27.247 回答