Question

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"`
}
Was it helpful?

Solution

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?
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top