1
votes

I am currently wrapping a Rest(ish) API. The JSON looks something like this, but more extensive:

{ 'a' : 'Bar1 Bar1B' }
{ 'a' : 'Bar2 Bar2A' }

This seems like it would be well represented by Enum types. For example:

data Foo = Foo { a :: Bar }

data Bar = Bar1 Bar1 | Bar2 Bar2

data Bar1 = Bar1A | Bar1B

data Bar2 = Bar2A | Bar2B

I'm having two problems.

While I can write ToJSON instances quite easily:

instance ToJSON Bar1 where
         ToJSON Bar1A = String "Bar1A"
         ToJSON Bar1B = String "Bar1B"

when I write the corresponding FromJSON instances, they fail to decode:

instance FromJSON Bar1 where
         parseJSON (String "Bar1A") = return Bar1A
         parseJSON (String "Bar1B") = return Bar1B
         parseJSON _ = mzero

Why is this?

Secondly, this seems like it will involve me writing a huge amount of boilerplate. Is there any way around this? Using Show/Read, or template haskell, for example?

1

1 Answers

4
votes

You can't decode a bare Bar1A value because a bare string is not valid JSON. Only arrays or objects are allowed at top-level.

Derived instances for simple examples like you're talking about here are quite straightforward using -XDeriveDataTypeable. See the Aeson docs for details.