klappvisor klappvisor - 1 year ago 89
JSON Question

How to serialize record sum data type in Aeson without tag?

I have data type with multiple constructors, for example

data AB = A
ab :: Text
, a :: Text
| B
ab :: Text
, b :: Text
} deriving (Generic)

Right now when I use Aeson to serialize
it generated to following JSON:

"tag": "A",
"ab": "some text",
"a": "some text"

I know that it's possible to use SumEncoding to manipulate how constructor will be handled, but could not find what I want.

Is it possible somehow to omit
field in serialized JSON? I need only one way serialization (no reason to keep it to deserialize it), but data type is pretty big to write how to serialize it manually.

Answer Source

A hacky way is to simply delete the tag from the resulting object:

{-# LANGUAGE DeriveGeneric #-}
import Data.Aeson
import Data.HashMap.Strict
import Data.String
import Data.Text
import GHC.Generics

data AB
  = A { ab :: Text
      , a  :: Text
  | B { ab :: Text
      , b  :: Text
  deriving Generic

instance ToJSON AB where
  toJSON ab = case genericToJSON defaultOptions ab of
    Object o -> Object (delete (fromString "tag") o)
    _ -> error "impossible"

It'll probably come back to bite you when the generic instance inevitably changes, though, so if you do this, be conscious of the technical debt you are choosing to take on.