Search code examples
haskellihp

Haskell Aeson return empty object


I'm trying to return a JSON data representation if not Nothing, and an empty JSON object if Nothing;

I know that I can do:

encode ()
-- "[]"

But now I'd like to have an empty object ("{}").

I have this, which works for generating JSON base on the given fields:

λ data Person = Person { id :: Integer, height :: Float } deriving (Show)
λ instance ToJSON Person where toJSON (Person { id = id, height = height }) = object [ "id" .= id, "height" .= height ]
λ encode (Person 1 72.8)
-- "{\"height\":72.8,\"id\":1}"

But eventually the absence of a Person would be represented with Nothing, if I do encode (Nothing) I get an error:

<interactive>:11:1: error:
    • Ambiguous type variable ‘a0’ arising from a use of ‘encode’
      prevents the constraint ‘(ToJSON a0)’ from being solved.
      Probable fix: use a type annotation to specify what ‘a0’ should be.
      These potential instances exist:
        instance ToJSON DotNetTime
          -- Defined in ‘aeson-1.4.7.1:Data.Aeson.Types.ToJSON’
        instance ToJSON Value
          -- Defined in ‘aeson-1.4.7.1:Data.Aeson.Types.ToJSON’
        instance (ToJSON a, ToJSON b) => ToJSON (Either a b)
          -- Defined in ‘aeson-1.4.7.1:Data.Aeson.Types.ToJSON’
        ...plus 26 others
        ...plus 63 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    • In the expression: encode (Nothing)
      In an equation for ‘it’: it = encode (Nothing)

Solution

  • encode Nothing will always return null. Encoding an empty object can be done by doing encode (object []). If you want to encode Nothings this way, you could write a custom encoding function for Maybe values like this.

    encodeMaybe :: ToJSON a => Maybe a -> ByteString
    encodeMaybe (Just x) = encode x
    encodeMaybe Nothing  = encode (object [])
    

    Or alternatively

    toJSONMaybe :: ToJSON a => Maybe a -> Value
    toJSONMaybe (Just x) = toJSON x
    toJSONMaybe Nothing  = object []