aeson icon indicating copy to clipboard operation
aeson copied to clipboard

Generic encoding incorrect for some cases

Open yav opened this issue 2 years ago • 1 comments

Consider a type like this:

data T = A { tag :: Int } | B

when using the default options for generic encoding and try to encode A { tag = 2 } the result is {"tag":2}, because the field tag overwrote the actual constructor tag A

yav avatar Apr 02 '23 22:04 yav

The default sum encoding is TaggedObject with tagFieldName and its docs say

So make sure that your record doesn't have a field with the same label as the tagFieldName. Otherwise the tag gets overwritten by the encoded value of that field!

So either we can somehow try to point out that in the docs more clearly (I have no idea how though), or change the default sum encoding to e.g. ObjectWithSingleField, which doesn't have such limitations. That however would be a very big breaking change (silently changing stuff for people, i.e. only proper encoding tests would find the change!), so I'm hesitant.

I'd advice you

  • to write instances out, like toEncoding = toEncoding myOptions (which you should do anyway, so toEncoding is derived, and not using toJSON), where myOptions = defaultOptions { ... }
  • write encoding (or better roundtrip) tests
  • Then you can change the "tag", or the sum encoding for a type with tag field.

phadej avatar Jun 20 '23 09:06 phadej