I've spent some time playing around with Aeson, but I can't get Algebraic Data Types to serialise nicely.
What I've tried is:
data Attach = Attach { tel :: String }
deriving (Show)
$(deriveJSON defaultOptions ''Attach)
data Fix = Fix { lat :: Double, lng :: Double }
deriving (Show)
$(deriveJSON defaultOptions ''Fix)
data MsgIn = AttachMsg Attach
| FixMsg Fix
deriving (Show)
$(deriveJSON defaultOptions ''MsgIn)
data MsgIn2 = MsgIn2 { attach :: Maybe Attach, fix :: Maybe Fix }
deriving (Show)
$(deriveJSON defaultOptions ''MsgIn2)
someFunc :: IO ()
someFunc = do
let attach = Attach "+447890"
let reply = AttachMsg attach
BL.putStrLn (encode reply)
let reply2 = MsgIn2 (Just attach) Nothing
BL.putStrLn (encode reply2)
The output is:
{"tag":"AttachMsg","contents":{"tel":"+447890"}}
{"attach":{"tel":"+447890"},"fix":null}
The output I'm looking for is:
{"attach":{"tel":"+447890"}}
but from the MsgIn
type, rather than MsgIn2
.
(The output of MsgIn2
gets quite close, but it's got an explicit null
.)
Is there a way of doing this in Aeson?
Update:
I added:
instance ToJSON MsgIn3 where
toJSON (AttachMsg3 (Attach tel)) = object ["attach" .= object ["tel" .= tel]]
...
let reply3 = AttachMsg3 attach
BL.putStrLn (encode reply3)
and got the answer I wanted: {"attach":{"tel":"+447890"}}
.
@bheklilr is there a way to use Attach's (already defined) serialisation, instead of defining it again?
I've tried some nonsense syntax, but understandably it doesn't compile:
instance ToJSON MsgIn3 where
toJSON (AttachMsg3 (Attach tel)) = object ["attach" .= (toJSON :: Attach)]