Why does json.Unmarshal work with reference but not pointer?

Solution 1:

You've encountered an InvalidUnmarshalError (see lines 109 and 110 in decode.go).

// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
// (The argument to Unmarshal must be a non-nil pointer.)

It seems the docs could do with some clarification as the quote above and the comment below from the Unmarshal source seem to contradict each other.

If the pointer is nil, Unmarshal allocates a new value for it to point to.

Solution 2:

Because your pointer is nil.

If you initialize it it works: http://play.golang.org/p/zprmV0O1fG

var animals *Animal = &Animal{}

Also, it can be spelled either way (consistency in a single doc would be nice, though): http://en.wikipedia.org/wiki/Marshalling_(computer_science)

Solution 3:

I believe the issue is that, while you can pass a pointer to nil to Unmarshal(), you can't pass a nil pointer value.

A pointer to nil would be like:

var v interface{}
json.Unmarshal(text, &v)

The value of v is nil, but the pointer to v is a non-zero pointer address. It's a non-zero pointer, which is pointing to a nil interface{} (which itself is a pointer type). Unmarshal doesn't return an error in this case.

A nil pointer would be like:

var v *interface{}
json.Unmarshal(text, v)

In this case, the type of v is pointer to an interface{}, but as with any declaration of a var in golang, the initial value of v is the type's zero-value. So v is a zero-value pointer, which means it isn't pointing to any valid place in memory.

As mentioned in the https://stackoverflow.com/a/20478917/387176, json.Unmarshal() needs a valid pointer to something, so it can change the something (be it a zero value struct, or a pointer) in place.

Solution 4:

I had a similiar condition before but in a different case. It is related with concept of interface in Go. If a function declares a interface as argument or return value, the caller have to pass or return the reference

In your case, json.Unmarshal accept interface as second argument