Skip to content
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

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

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

Comments

Projects
None yet
5 participants
@orcaman
Copy link

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor

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

This comment has been minimized.

Copy link
Contributor

commented Nov 19, 2015

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Contributor

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 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

Matthew Fisher
fix(api): make Routable a *bool
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

Matthew Fisher
fix(api): make Routable a *bool
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.
You can’t perform that action at this time.