-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: omitempty for arrays is confusing #29310
Comments
An array that has a bunch of 'zero values' is not empty. The list of zeros means something. I would expect the array to be printed as is shown in the "what did you see instead" (for example a zero matrix). I played around with this a little and think this is a real issue. My first attempt would be to implement the json.Marshaler interface for some type encapsulating [16]byte. type UUID [16]int
func (uuid UUID) MarshalJSON() ([]byte, error) {
for _, num := range uuid {
if num != 0 {
return json.Marshal([10]int(uuid))
}
}
return json.Marshal(/* some zero value */) // <--- this is the real problem in my opinion.
} Since it seams MarshalJSON is called after the value is established to not be zero, no matter what you put return from MarshalJSON, the value returned is not considered to be an empty value. I think a json.ErrValueIsZero would be useful in this situation. So you can override the zero-ness of a type. The only other solutions that I can think of would be to
I don't really love either of these options too much. Notes (my playground): https://play.golang.org/p/GV8rX6f30ba |
IMO, it doesn't seem confusing to me. The array indeed contains 16 zeros (which are totally valid values). So why should it be If you want this behavior to be there, this should be a proposal instead of a bug report. |
This is a bug in the semantics of
There aren't any caveats added there. For all the other items in the list, any type of those things is considered empty, but with arrays only specific types of arrays can be considered empty and those are arrays that it is doubtful someone would use as a struct field. What most users who add The confusing part is the definition of an empty array. It doesn't make much sense to provide a struct tag for something that is quite useless in practice and call it out in the documentation. A struct field with |
It's really not a semantics bug, though. Since an array is not a pointer type,
You may prefer this, but many (for example me) do not. As far as Javascript/JSON is concerned, an array with 16 0-valued elements is not an empty array, so considering it as such would be incorrect, wouldn't it? Why not just use
I don't disagree that you'd probably never have I do agree with @crhntr that a special error to return from |
Reminds me of #28391 - in that issue, I don't personally have an opinion, but I think the current behavior of For example, I presume that a slice with zero length and non-zero capacity is empty, but non-zero. That distinction could break dozens of programs in the wild if we suddenly change the meaning of |
@skriptble I also run into this issue using UUID's. Did you find a workaround? |
@andybons I see the milestones on this issue have been updated twice, but it doesn't seem like there was a resolution on what to do going forward. I assume changing the default behavior of
that types can implement. The existing
Any thoughts as to which solution would be better? I can pick up this task and file a PR once we've decided on a way forward. |
@divjotarora sounds like you want a proposal as you’re looking to add to the API surface. |
Also, please search before making either of these suggestions. I'm pretty sure the first one has been made before, for example. |
@mvdan Are you referring to #11939? I read through it, and it seems like there are concerns about |
@divjotarora yes, that's the issue I mean. I think a new proposal would be so alike, that it would be considered a duplicate. If you have something to add to the original thread, I'd do it there. |
I was recently tripped up by this. I think the issue (for me) was that all of "false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string" are also the zero value for their type, and it's easy to then (wrongly) think "zero values are omitted". The confusion comes from "empty array": by itself, "array" can mean an array of 0, 1, or more elements. It took me a second take to realize "empty array" can only ever refer to zero-length arrays. I suggest changing the documentation to:
|
@pmahoney that seems reasonable - want to send a patch? |
Hi all, we kicked off a discussion for a possible "encoding/json/v2" package that addresses the spirit of this proposal. See the "omitzero" struct tag option under the "Struct tag options" section, which omits a struct field if it is the zero Go value (or has a |
Arrays are never considered empty because they are full of zeros by default. So all attributes were getting encrypted (with a key of zeros) when set. Switching to a slice fixes this. golang/go#29310
We can now use |
This CL is inspired by: golang#29310 (comment) When I read omitempty option in encoding/xml package, I find it's a bit different than encoding/json package. I think it's more precise to say: "any array, slice, map, or string of length zero." Update golang#29310 Change-Id: I64aefea34327c503a9ab33fceca3e02a62cb673a
Change https://go.dev/cl/621835 mentions this issue: |
This CL is inspired by: #29310 (comment) When I read omitempty option in encoding/xml package, I find it's a bit different than encoding/json package. I think it's more precise to say: "any array, slice, map, or string of length zero." Update #29310 Change-Id: Ia77167c3155411640224b349d4b34d0bb91ee11e GitHub-Last-Rev: a4cf00d GitHub-Pull-Request: #69984 Reviewed-on: https://go-review.googlesource.com/c/go/+/621835 Auto-Submit: Ian Lance Taylor <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Joseph Tsai <[email protected]> Reviewed-by: Michael Pratt <[email protected]>
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
https://play.golang.org/p/NlRBFTZHFYd
What did you expect to see?
What did you see instead?
This is caused by
isEmptyValue
insideencoding/json
checking to see if the length of the array is 0. For people actually using an array (and not a slice), it is unlikely that they would ever use an array of zero length. It is likely, however, that they might want to omit the result if all of the values in the array are empty. For example, if a user is using[16]byte
to represent a UUID, they might want to omit encoding it if it is all zeroes. This was brought up in #11939, specifically this comment. It would be nice if we could do this generically for arrays with values we can determine are empty.The text was updated successfully, but these errors were encountered: