我需要以灵活的方式指定用于解码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]]}
。我想解码为特定(struct)类型的数组而不是[]interface{}
,而不是在编译时指定它。
在没有预先创建阵列的情况下,这有可能吗? (退回的项目数量未知)
我现在能想到的唯一方法是稍后再次对返回的地图进行编码,并将它们解码为指定的类型,这会产生不必要的处理开销。
答案 0 :(得分:5)
如果在编译时没有指定它,你仍然需要在某处指定它。
如果在检索Json数据之前指定,您只需执行一个切换案例,将其解组到您想要的对象。
如果在 Json数据中指定,您可以将“灵活”部分编组为json.RawMessage
,以便在确定适合的结构类型后对其进行处理:
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
}
}