go-json-experiment / json

Experimental implementation of a proposed v2 encoding/json package
BSD 3-Clause "New" or "Revised" License
341 stars 11 forks source link

Decoding of custom uint8 stored in a slice cannot be decoded properly #36

Open element-of-surprise opened 2 months ago

element-of-surprise commented 2 months ago

Marshalling the following:

m := map[string]any{
    "Categories": []uint8{1},
}

Produces:

{"Categories":"AQ=="}

This causes the unmarshal to come back as a string instead of a []uint8. I'm guessing this has something to do with the encoder thinking that []uint8 is not an array of numbers but []byte and therefore tries to deal with that encoding []byte as a string.

This is expected behavior, as seen in the current standard library,.

Here is a playground link to demonstrate this. https://go.dev/play/p/Hhja0Y2QL_t

What doesn't work in the new package is if you decode that back into a struct that has a custom type for that uint8 value. Something like type Category uint8.

Using encoding/json to decode the encoded json into a struct: https://go.dev/play/p/8TCLcNznOdu

Using go-json-experiment to decode the encoded json into a struct (does not work): https://go.dev/play/p/ZSlqMAwQjX0

Same, but change custom type for uint8 to just uint8 (works): https://go.dev/play/p/QbDG2pCgLuO

As a note: This package is great, and I've got to imagine so much work and pain with so many corner cases. Thanks for all the hard work.

mvdan commented 2 months ago

How would you expect this to work for any Go types? JSON doesn't have a bytes type/kind, so roundtripping []byte without Go type information is not possible.

element-of-surprise commented 2 months ago

I'm going to need to expand the problem here. I was trying to simplify it to its core, but what I really need to show is the change in expected behavior. Trying to make it simpler made it show expected behavior.

And I probably need to change the title but let me update here and then I'll amend.

Encoding as a string encoding seems to be the behavior in encoding/json. However, that package can decode back into []uint8 of a custom type, this package does not. This may be expected new behavior.

Using encoding/json to decode the encoded json into a struct: https://go.dev/play/p/8TCLcNznOdu

Using go-json-experiment to decode the encoded json into a struct (does not work): https://go.dev/play/p/ZSlqMAwQjX0

Same, but change custom type for uint8 to just uint8: https://go.dev/play/p/QbDG2pCgLuO

element-of-surprise commented 2 months ago

Updated title and problem statement. Sorry for the adjustment.