surbhi surbhi - 7 days ago 5
JSON Question

How to unmarshal from interface{} to interface{} in Go

There are multiple nodes in my system which communicate through RPC. I am trying to send a map[string] interface{} to another node through RPC. Sender uses json.Marshal and receiver uses json.Unmarshal to get the map.
Let us say at the sender side, map contains [1] => 2 where 2 is of type uint32.

The problem is Unmarshal tries to find the type of underlying data and converts 2 to float64 type according to its default behavior as specified here https://blog.golang.org/json-and-go. Later, casting float64 to uint32 causes panic.

I refered to How to unmarshal json into interface{} in golang? . But for this, we need to know the type of data. In my case data can be of any type so I want to keep it as interface{}. How do I unmarshal from interface{} to interface{}?

Answer

Unfortunately using the encoding/json package you can't, because type information is not trasmitted, and numbers by default are unmarshalled into values of float64 types if type information is not present. You would need to define struct types where you explicitly state the field is of type uint32.

Alternatively you may opt to use encoding/gob which does transmit and preserve type information. See this example:

m := map[string]interface{}{"1": uint32(1)}

b := &bytes.Buffer{}
gob.NewEncoder(b).Encode(m)

var m2 map[string]interface{}
gob.NewDecoder(b).Decode(&m2)
fmt.Printf("%T\n%#v\n", m2["1"], m2)

Output (try it on the Go Playground):

uint32
map[string]interface {}{"1":0x1}
Comments