Unmarshaling JSON: Pointers vs. References
The json.Unmarshal function allows us to convert JSON data into a Go struct. While the documentation suggests that it can allocate a new value if the pointer is nil, this is not the case.
Consider the following example:
var animals Animal err := json.Unmarshal(jsonBlob, &animals)
This works as expected because animals is a non-nil pointer. However, if we change animals to an uninitialized pointer:
var animals *Animal err := json.Unmarshal(jsonBlob, animals)
This fails with the obscure error message:
json: Unmarshal(nil *main.Animal)
This error stems from an InvalidUnmarshalError, which is thrown when an invalid argument is passed to Unmarshal. The documentation does not explicitly state that the pointer must be non-nil, which could lead to confusion.
The conflicting quote in the documentation, which suggests that Unmarshal can allocate a new value for nil pointers, may be referring to the behavior of the reflect.New function, which is used internally by Unmarshal to create a new value when the pointer is nil. However, reflect.New only works for certain types, such as structs and slices. It does not work for pointers to primitive types, such as *int or *string.
In summary, json.Unmarshal requires a non-nil pointer as its second argument. It cannot allocate a new value for nil pointers of primitive types. Therefore, it is important to ensure that the pointer is non-nil before attempting to Unmarshal JSON data into it.
The above is the detailed content of Why Does `json.Unmarshal` Fail with a Nil Pointer to Primitive Types?. For more information, please follow other related articles on the PHP Chinese website!