Question

Does anybody know where I can find documentation on how ADTs are translated to Json by Aeson's ToJSON? I'm using Haskell for a backend application, and I'm trying to write the JSON decoder for another functional language on the front end, so I'd like to use the same JSON format so that I can send messages between them.

Was it helpful?

Solution

I don't think it's very well documented, but I've had a lot of success in similar situations by using a QuickCheck Arbitrary instance to generate large numbers of source types, encoding them to JSON, and then using them as a gold-standard tests for your front-end.

You can also garner some amount of intuition for how Aeson's Template Haskell encoding works by peeking around at the configurable Options type in Data.Aeson.TH. In particular take a look at SumEncoding which will let me explain, for instance, that Either is encoded using ObjectWithSingleField, i.e. {"Left": 3} for Left 3.

OTHER TIPS

Of course, looking at the cases generated by QuickCheck is a kind of practical solution.

But when thinking about it, it is convenient to have some conceptual picture of the possible translation options.

I've gone through through all the available options for the translation of sum types in aeson and generic-aeson in an answer here, with examples.

But the specifics of that example is that the data are records. Something may change in the examples if they are not.

So my conceptual picture (perhaps, not complete and quite correct yet) is like this:

  • if the type is not a non-trivial sum,

    • but is like a newtype (or has a single unary data constructor), this is simply a no-op in JSON.
    • If it is a record, it becomes an object.
    • If it is a real, non-trivial product type (and not record), then .... (probably an array).
  • there are special basic cases: Maybe a, [a], various String-like types, Bool, Int-like, ...

  • if the type is a non-trivial sum, then it is important whether it is an "enum" (having all nullary constructors) or not.

    • enums are translated into strings with the values;
    • non-enums according to a SumEncoding option:
      • whether it is a record or not may also make a difference (like in the first case of non-sums).

Please correct me or complete missing points.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top