Question

I have the following problem, I have a JSON format with optional keys that I need to generate from my haskell code.

Lets make an example

{-# LANGUAGE DeriveGeneric #-}

import GHC.Generics
import Data.Aeson

data Person = {
    name :: String,
    shoeSize :: Maybe Int,
    favoriteColor :: Maybe String,
    favoriteFood :: Maybe StringC
} deriving (show, eq, generic)

instance ToJSON Person -- Generic instance

now, if I try encoding a Person without a shoesize I still get a key "shoeSize" set to null, what is the Aeson way of making keys optional in encoding

edit, example of an encode

encode $ Person "windwarrior" Nothing "green" Nothing

should result in

{"name":"windwarrior", "favoriteColor":"green"}
Was it helpful?

Solution

Use TemplateHaskell to derive the ToJSON instance instead of Generic. The TH functions optionally take an Options which has the omitNothingFields option.

OTHER TIPS

There is the Options datatype with an omitNothingFields field for Generics as well so you don't have to use TemplateHaskell, however there's currently (v0.11.2.0) a bug that makes it generate invalid JSON under certain circumstances, e.g. several record fields. It has been fixed but is in master.

You can also handwrite instances if you prefer, for your example:

instance ToJSON Person where
    toJSON (Person name shoeSize favoriteColor favoriteFood) = object fields
      where
        consMay attr = maybe id ((:) . (attr .=))
        conss = consMay "shoeSize" shoeSize
              . consMay "favoriteColor" favoriteColor
              . consMay "favoriteFood" favoriteFood
        fields = conss ["name" .= name]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top