Why does json.Unmarshal return a map instead of the expected struct?

我们两清 提交于 2019-12-10 16:13:26

问题


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"`
}

回答1:


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?
}


来源:https://stackoverflow.com/questions/21468741/why-does-json-unmarshal-return-a-map-instead-of-the-expected-struct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!