Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Drop the "key not found" exception in favor of monoid empty value #108

nikita-volkov opened this Issue · 8 comments

4 participants


Please consider this record type

data A = A { a :: Maybe String, b :: Int, c :: [Int] }

What's common about its field types is that they all have Monoid instances.

What I propose is instead of failing the parser with a "key not found" exception in case when a JSON value with some missing fields is provided (for instance, {"a": "abc", "b": 3} - field "c" is missing) to provide a Monoid's empty value for the type. So for input:

{"a": "abc", "b": 3}

the decoding would result in

A (Just "abc") 3 []

and for an absolutely empty object


it would result in all the monoids getting empty values, i.e:

A Nothing 0 []

The parser should however still fail for types not having the Monoid instances.

Implementing this will also open an ensuing possibility of greatly reducing the generated JSON, which will provide all kinds of benefits, such as traffic and storage reduction.


I don't see how to implement this. (Also, there is not a Monoid instance for common types such as Int or Bool, which somewhat defeats the usefulness of this.)


@bos I understand. Well, the solution doesn't have to be based on the Monoid. It could probably treat all the basic types as special cases. The one type which IMO it just must handle is Maybe. Because otherwise there are plenty of cases when it is just impossible to decode the JSON into a record with generics.

Need a practical example? Here's a standard "design" document of CouchDB:

      "map":"funcion(doc){/* the implementation */}"

Here's a pretty straight-forward record representation for it:

data Design a 
  = Design {
      views :: Map Text View  

data View 
  = View {
      map :: Text,
      reduce :: Maybe Text

But it won't parse since the "view" json value doesn't contain a "reduce" field. What makes it worse is that there are plenty of situations when you have no control over incomming JSON.


Why not just use the .:? operator for that? As in:

instance FromJSON View where
  parseJSON = withObject "View" $ \obj -> 
                View <$> obj .:  "map"
                     <*> obj .:? "reduce"  

@basvandijk Thanks but I wanted to point out that the problem is general enough for there to exist a generic solution.


The problem is that typeclasses are not well suited to "I want this behaviour for every type save for these exceptions". When I say that I don't see how to implement this, that's the problem I am referring to.


@bos Okay. But what about the specific types? Forget about Monoid. I mean, since there's a limited set of types which support JSON out of the box, why not extend their individual implementations to somehow treat the missing value?


see issue #77 for maybe treatment. In short: try to use aeson-smart.


I'm going to close this. If you come up with a practical proposal for what it should like like, please submit a pull request and I'll take a look.

@bos bos closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.