为什么json.Unmarshal返回一个映射而不是预期的结构? [英] Why does json.Unmarshal return a map instead of the expected struct?
问题描述
看到这个操场: http://play.golang.org/p/dWku6SPqj5
基本上,我正在处理的库接收 interface {}
作为参数,然后需要 json.Unmarshal
来自一个字节数组。在封面下, interface {}
参数是一个与字节数组的json结构相匹配的结构,但该库没有对该结构的引用(但它的确如此有一个参考相应reflect.Type通过)。
为什么json包不能检测底层类型?由于某种原因,它将返回一个简单的映射,而不是实际的struct。
以下是代码:
<$ p $
导入fmt
导入encoding / json
导入反映
func main (){
good()
bad()
}
func good(){
var ping Ping = Ping {}
deserialize([] byte(`{id:42}`),& ping)
fmt.Println(DONE:,ping.ID)
}
func bad(){
var ping interface {} = Ping {}
反序列化([] byte(`{id:42}`),&ping)
fmt。 Println(DONE:,ping)//这是一张简单的地图,不是Ping。为什么?
$ b func反序列化(stuff [] byte,thing interface {}){
value:= reflect.ValueOf(thing)
fmt.Printf( + v |%v \ n,value,value.Kind())
err:= json.Unmarshal(stuff,thing)
if err!= nil {
$ pan $ {
}
}
类型Ping结构{
ID int`json:id`
}
您已传递给 json
一个指向抽象接口的指针。您应该简单地将一个指针传递给 Ping
作为抽象接口:
func bad(){
var ping interface {} =& Ping {} //<<<<<这个
反序列化([] byte(`{id:42}`),ping)//<<和这
fmt.Println(DONE:,ping)//这是一张简单的地图,不是Ping。为什么?
}
但是,如果你说你没有指针投掷ton interface {}
,你可以使用reflect创建一个新的指针,反序列化到它,并将值复制回来:
< pre $ func bad(){
var ping interface {} = Ping {}
nptr:= reflect.New(reflect.TypeOf(ping))
)deserialize([] byte(`{id:42}`),nptr.Interface())
ping = nptr.Interface()
fmt.Println(DONE:,ping) //这是一张简单的地图,而不是Ping。为什么?
}
See this playground: http://play.golang.org/p/dWku6SPqj5
Basically, the library I'm working on receives an interface{}
as a parameter and then needs to json.Unmarshal
that from a byte array. Under the covers, the interface{}
parameter is a struct that matches the json structure of the byte array but the library doesn't have a reference to that struct (but it does have a reference to the corresponding reflect.Type through).
Why can't the json package detect the underlying type? For some reason it's giving back a simple map instead of the actual struct.
Here's the code:
package main
import "fmt"
import "encoding/json"
import "reflect"
func main() {
good()
bad()
}
func good() {
var ping Ping = Ping{}
deserialize([]byte(`{"id":42}`), &ping)
fmt.Println("DONE:", ping.ID)
}
func bad() {
var ping interface{} = Ping{}
deserialize([]byte(`{"id":42}`), &ping)
fmt.Println("DONE:", ping) // It's a simple map now, not a Ping. Why?
}
func deserialize(stuff []byte, thing interface{}) {
value := reflect.ValueOf(thing)
fmt.Printf("%+v | %v\n", value, value.Kind())
err := json.Unmarshal(stuff, thing)
if err != nil {
panic(err)
}
}
type Ping struct {
ID int `json:"id"`
}
You've passed to json
a pointer to an abstract interface. You should simply pass a pointer to Ping
as an abstract interface:
func bad() {
var ping interface{} = &Ping{} // <<<< this
deserialize([]byte(`{"id":42}`), ping) // << and this
fmt.Println("DONE:", ping) // It's a simple map now, not a Ping. Why?
}
But if as you said you don't have a pointer to cast ton an interface{}
, you can use reflect to create a new pointer, deserialize into it, and copy the value back:
func bad() {
var ping interface{} = Ping{}
nptr := reflect.New(reflect.TypeOf(ping))
deserialize([]byte(`{"id":42}`), nptr.Interface())
ping = nptr.Interface()
fmt.Println("DONE:", ping) // It's a simple map now, not a Ping. Why?
}
这篇关于为什么json.Unmarshal返回一个映射而不是预期的结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!