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

marshaling byte slice ignores json.Marshaler/encoding.TextMarshaler interfaces #16

Closed
wI2L opened this issue Dec 7, 2019 · 9 comments · Fixed by #17
Closed

marshaling byte slice ignores json.Marshaler/encoding.TextMarshaler interfaces #16

wI2L opened this issue Dec 7, 2019 · 9 comments · Fixed by #17
Assignees
Labels
bug Something isn't working

Comments

@wI2L
Copy link

wI2L commented Dec 7, 2019

When a codec is created for a byte-slice type at

case bytesType:

it ignores the fact that the type could be implementing the json.Marshaler or encoding.TextMarshaler interfaces. This should be considered in priority, to be compliant with the standard library.

The following playground demonstrates the issue:
https://play.golang.org/p/Bm0d3jsWkZf

The relevant code can be found in the standard library at https://github.com/golang/go/blob/da4d58587e0e4028ea384580053c3c455127e446/src/encoding/json/encode.go#L415
The function newTypeEncoder checks in priority if the reflect.Value implements one of the interfaces.

@achille-roussel
Copy link
Contributor

Thanks for raising the issue!

I could be wrong, but I don't think the issue comes from the comparison to bytesType, because this is just a code path to match the []byte type exactly (for example https://play.golang.org/p/JDkXu1XkRgE).

I'm going to look into it, it should be an easy fix.

@achille-roussel achille-roussel self-assigned this Dec 7, 2019
@achille-roussel achille-roussel added the bug Something isn't working label Dec 7, 2019
@wI2L
Copy link
Author

wI2L commented Dec 7, 2019

@achille-roussel What I meant was the comparison to bytesType is made before checking if the type implement either of json.Marshaler or encoding.TextMarshaler. The newTypeEncode function of the standard library check for (JSON|Text)Marshaler first.

@achille-roussel
Copy link
Contributor

Yes but in this case we wouldn't enter this code path at all, which means we'll fallback to checking whether the type implements the interfaces below.

@wI2L
Copy link
Author

wI2L commented Dec 7, 2019

@achille-roussel You are right, I confused named byte slice type and byte slice type regarding the code part I mentionned as the source of the error.

@achille-roussel
Copy link
Contributor

No worries. It was an edge case because we have tests that verified this behavior already, but it turned out the zero-value of slice types implementing json.Marshaler was being misinterpreted, and we were missing a test for this specific case.

@wI2L
Copy link
Author

wI2L commented Dec 7, 2019

Perhaps constructSliceCodec should be responsible for returning a codec that uses encodeBytes and decodeBytes if the kind of the slice element is uint8, and it doesn't implements either the json.Marshaler/encoding.TextMarshaler interfaces, as in https://github.com/golang/go/blob/da4d58587e0e4028ea384580053c3c455127e446/src/encoding/json/encode.go#L864.

@achille-roussel
Copy link
Contributor

achille-roussel commented Dec 8, 2019

The fix was a bit more subtle than I anticipated actually: the issue you reported was just the fact that we were mistakenly encoding zero-value slices as null when they implemented json.Marshaler, but I added a couple more tests and noticed a there were differences in encoding based on whether a value will be addressable or not (here's an example https://play.golang.org/p/qRwJTqQodUi).

This is kind of crazy, and I hope no code out there relies on this behavior... anyways, it should be fixed in #17

@wI2L
Copy link
Author

wI2L commented Dec 8, 2019

@achille-roussel Ahaha, I know right. This was a pain to implement for me as well.
Edit: This reminds me that you should double check if the current implementation is subject to the bug I reported at golang/go#34235. But from what I see, the check at

switch v.Kind() {
should be enough.

@achille-roussel
Copy link
Contributor

I added a test for that case as well, it seems like we're handling it fine 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants