为什么json.Unmarshal返回一个映射而不是预期的结构? [英] Why does json.Unmarshal return a map instead of the expected struct?

查看:126
本文介绍了为什么json.Unmarshal返回一个映射而不是预期的结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看到这个操场: 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆