Skip to content

encoding/json: Marshaller omits false booleans as if they were nil #13284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
orcaman opened this issue Nov 17, 2015 · 5 comments
Closed

encoding/json: Marshaller omits false booleans as if they were nil #13284

orcaman opened this issue Nov 17, 2015 · 5 comments

Comments

@orcaman
Copy link

orcaman commented Nov 17, 2015

It appears that the Marshal function from encoding/json treats false booleans as if they were nil values, and thus it omits them from the resulted json. I believe this behavior is a bug. I couldn't find reference in the json spec, but it has caused some issues with my client code, that makes a distinction between a non-existent boolean and a false boolean.

See example here: http://play.golang.org/p/i3cNXqorif

@cespare
Copy link
Contributor

cespare commented Nov 17, 2015

This is working as intended. false is the zero value of booleans, and your json struct tag has omitempty. As you can see from t2, if you don't use omitempty, the value isn't omitted.

@cespare
Copy link
Contributor

cespare commented Nov 17, 2015

Actually that's slightly misleading: it's not that omitempty omits precisely zero values; the set of omitted values is listed in the Marshal documentation:

The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero.

@spenczar
Copy link
Contributor

If you need to make a distinction between a non-existent boolean and false boolean, use a *bool in your struct, like this:

type t struct {
    Autoplay *bool `json:"autoplay,omitempty"`
}

You'll have to do the extra work of checking that t.Autoplay is not nil, but that's unavoidable - it sounds like you want this ternary logic.

@orcaman
Copy link
Author

orcaman commented Nov 20, 2015

@cespare Considering golang's design where primitive types are always initialized to empty values, your comment makes perfect sense. So I realize this is not a bug, but it's also somewhat confusing and perhaps even unexpected. When writing go code, this isn't a big deal. But in the case of JSON data being passed from client to server (one of the largest use cases of JSON) , this makes go somewhat inconsistent with the rest of the world (clients and servers), and can confuse a lot of people. Not sure what a good solution would be.

@spenczar that's a great idea, thanks. That's exactly what I was after.

@rsc
Copy link
Contributor

rsc commented Dec 28, 2015

A boolean only has two values. You can either send false or not, depending on what tag you put on the variable. If you need a three-valued boolean, that's not a boolean. As @spenczar suggested, *bool is a good choice in this case.

@rsc rsc closed this as completed Dec 28, 2015
bacongobbler pushed a commit to bacongobbler/controller-sdk-go that referenced this issue Aug 10, 2016
bacongobbler pushed a commit to bacongobbler/controller-sdk-go that referenced this issue Aug 10, 2016
fixes the issue where the client would send an empty request on `deis routing:disable`.

see golang/go#13284
bacongobbler pushed a commit to bacongobbler/controller-sdk-go that referenced this issue Aug 11, 2016
fixes the issue where the client would send an empty request on `deis routing:disable`.

see golang/go#13284
@golang golang locked and limited conversation to collaborators Dec 29, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants