Revisiting JSON in Haskell

I just received an email with some praise for my earlier post on JSON in Haskell–it’s always nice to receive some praise ;-) However, the sender also mentioned that the mLookup function as coded there would blow up on incomplete JSON objects. That was by design, as a simplification, but the sender needed to deal with just that and asked if I had some more elegant solution than making every field in the data type a Maybe.

As I said, it’s always nice to receive praise, so here’s one solution that came to mind as I was reading the email.

I should mention that it relies on there being a reasonable default value for each type of the fields, and that the default is the same for all fields sharing a type.

First off, define a type class for types with default values:

class Defaultable d where
    def :: d

Then modify mLookup so that it uses Defaultable. I renamed it to mLookupAndReadJSON:

mLookupAndReadJSON a as = maybe def readJSON (lookup a as)

Now we need to provide some instances of Defaultable too. I limit this example to cover only GlossDef, so only the following instances are required:

instance Defaultable [a] where
    def = []

instance Defaultable a => Defaultable (Result a) where
    def = Ok def

Now it’s possible to decode incomplete JSON objects:

ghci> decode "{ \"GlossSeeAlso\": [\"GML\", \"XML\"] }" :: Result GlossDef
Ok (GlossDef {glossDefPara = "", glossDefSeeAlso = ["GML","XML"]})

I’m sure there are other ways of achieving what the author of the email asked for. Please let me know of them in comments.


Neil, cmdargs is where I first came across this little trick :-) It’s also coded up in Data.Default, which can be found on Hackage.

Leave a comment