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

proposal: encoding/json: allow returning nil from MarshalJSON to omit the field #50480

Open
mitar opened this issue Jan 6, 2022 · 0 comments
Open
Labels
Projects
Milestone

Comments

@mitar
Copy link

@mitar mitar commented Jan 6, 2022

Currently even if one implements MarshalJSON on a struct there is no way to prevent its inclusion into the parent struct. E.g.:

type Foo struct {
	Field Field `json:"field"`
}

type Field struct {
	DataPublic bool
	Value      interface{}
}

func (f Field) MarshalJSON() ([]byte, error) {
	if f.DataPublic {
		return json.Marshal(f.Value)
	} else {
		return []byte("null"), nil
	}
}

(Full example: https://go.dev/play/p/A0wKfuZgURw)

The best one can do is return null. But what if one wants to fully omit the field? This is not possible. Or one has to implement MarshalJSON on the parent struct, but that is not nice from composability perspective (one would have to implement this for every struct which includes Field).

I propose that it should be allowed to return nil, nil from MarshalJSON to signal that the field should be omitted in the parent struct. Currently returning nil, nil does fails with error unexpected end of JSON input because the resulting JSON is malformed. That means that nobody can rely on this behavior really for correct JSON output (maybe only to catch errors?), so I do not think we would be breaking any real backwards compatibility if we introduce this, or at least I believe benefits are bigger here. In any case, if you want previous behavior, you can return []byte{} and then it will continue to error in the same way. Doing JSON marshal of a struct itself which returns nil is compatible enough in my view: if caller just assumes they are getting []byte slice, nil will mostly behave for them as an empty slice. If they are able to handle it anyway.

Implementing this would also provide a solution for the issue that omitempty does not work with structs: one could implement MarshalJSON which checks if the value is zero and return nil if it is so. This would be useful only when implementor of the type is the user of it at the same time, but one can always make a new type as a user and then implement MarshalJSON there. I think it is an useful step in addressing that.

Returning nil to omit the field seems to be also something others expected to work and has been also proposed in the past, but inside a bigger discussion, so this can serve as a proposal for just this feature.

@mitar mitar added the Proposal label Jan 6, 2022
@gopherbot gopherbot added this to the Proposal milestone Jan 6, 2022
@ianlancetaylor ianlancetaylor added this to Incoming in Proposals Jan 7, 2022
@ianlancetaylor ianlancetaylor changed the title proposal: encoding/json: Allow returning nil from MarshalJSON to omit the field proposal: encoding/json: allow returning nil from MarshalJSON to omit the field Jan 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Proposals
Incoming
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants