Skip to content

encoding/json: unmarshalling null into non-nullable golang types #33835

Open
@Qhesz

Description

@Qhesz

Does this issue reproduce with the latest release?

As of 1.12, yes.

What did you do?

I unmarshalled null into an int, string, bool etc. (any non-nullable Golang type)

What did you expect to see?

A type mismatch error, similar to if I'd unmarshalled a string into an int, or any other type mismatch.

What did you see instead?

No error at all, unmarshalling 'succeeds' at deserialising null into my non-nullable type.

Discussion

I'm aware of #2540 , I'm specifically arguing for the reversal of that decision. I'm aware the documentation says "Because null is often used in JSON to mean “not present,” unmarshalling a JSON null into any other Go type has no effect on the value and produces no error.". I'm arguing against that behaviour.

1.

The unmarshaller shouldn't have an opinion on what null "means", it should accurately map json types into their golang equivalents.

2.

If I'm unmarshalling into a specific golang type, I've gone to the effort of statically defining the type that I expect. The unmarshaller should assist me, and reject any poorly typed input (which it does well for all types other than null). If I wanted to marshal into a nullable type, I would have specified a nullable type.

3.

myVar int and myVar *int currently behave the same way when unmarshalling. In golang, an optional value is often implemented as a pointer, so I read these as "int" and "optional int", and I would expect them to behave differently.

4.

Currently json struct tags using the standard library, and db struct tags using the standard library for sql behave differently. In the sql libraries, nullable types are explicit, and trying to unmarshal an sql NULL into a non-nullable type is an error. For sql, like my point 2 above, a pointer to a value can be used as a nullable version of that type.

5.

It is impossible for me to override this behaviour of the unmarshaller. Defining my own type NoReallyIMeantInt int doesn't help. Unmarshalling still succeeds, because the current code parses the null first, and returns early without looking at the Golang type. (It explicitly sets Interfaces, pointers, maps and slices to their zero values, and ignores all other types.)

Practicalities

I'm aware this decision was made a long time ago. Realistically, what are the chances that this will be fixed now? Is it a compatibility concern? Do we think people deliberately rely on the current unmarshalling behaviour of null?

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsDecisionFeedback is required from experts, contributors, and/or the community before a change can be made.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions