Benjamin Malley
Benjamin Malley

Reputation: 223

How to Unmarshal JSON into an interface in Go

I am trying to simultaneously unmarshal and strip fields from a number of different JSON responses into appropriate Go structs. To do this, I created a Wrappable interface that defines the Unwrap method (which strips the appropriate fields) and pass that interface to the code that unmarshals and unwraps. It looks like the following example (also at http://play.golang.org/p/fUGveHwiz9):

package main

import (
    "encoding/json"
    "fmt"
)

type Data struct {
    A string `json:"a"`
    B string `json:"b"`
}

type DataWrapper struct {
    Elements []Data `json:"elems"`
}

type Wrapper interface {
    Unwrap() []interface{}
}

func (dw DataWrapper) Unwrap() []interface{} {
    result := make([]interface{}, len(dw.Elements))
    for i := range dw.Elements {
        result[i] = dw.Elements[i]
    }
    return result
}

func unmarshalAndUnwrap(data []byte, wrapper Wrapper) []interface{} {
    err := json.Unmarshal(data, &wrapper)
    if err != nil {
        panic(err)
    }
    return wrapper.Unwrap()
}

func main() {
    data := `{"elems": [{"a": "data", "b": "data"}, {"a": "data", "b": "data"}]}`
    res := unmarshalAndUnwrap([]byte(data), DataWrapper{})
    fmt.Println(res)
}

However, when I run the code, Go panics with the following error:

panic: json: cannot unmarshal object into Go value of type main.Wrapper

It seems the unmarshaller doesn't want to be passed a pointer to an interface. I am somewhat surprised by this given that I can get at the underlying type and fields using the reflect package within the unmarshalAndUnwrap method. Can anyone provide insight into this problem and how I might work around it?

Upvotes: 1

Views: 5785

Answers (1)

creack
creack

Reputation: 121492

As you stated, passing a non-pointer fails. Why are you trying to do this anyway?

Replace

res := unmarshalAndUnwrap([]byte(data), DataWrapper{})

by

res := unmarshalAndUnwrap([]byte(data), &DataWrapper{})

It should do the trick and it avoid unnecessary copy.

This error should help you understand: http://play.golang.org/p/jXxCxPQDOw

Upvotes: 2

Related Questions