我有多个构造函数的数据类型,例如
data AB = A
{
ab :: Text
, a :: Text
}
| B
{
ab :: Text
, b :: Text
} deriving (Generic)
现在,当我使用Aeson将其生成的A
序列化为跟随JSON:
{
"tag": "A",
"ab": "some text",
"a": "some text"
}
我知道可以使用SumEncoding
来操纵构造函数的处理方式,但无法找到我想要的内容。
是否有可能以某种方式省略序列化JSON中的tag
字段?我只需要一种方式序列化(没有理由让它反序列化),但数据类型对于编写如何手动序列化来说非常重要。
答案 0 :(得分:4)
Options
有一个sumEncoding
字段,defaultOptions
将此字段设置为defaultTaggedObject
。
将其设置为UntaggedValue
(来自SumEncoding
,在aeson-1.0.0.0和更高版本中可用)应该可以满足您的需求。
答案 1 :(得分:2)
自己定义ToJSON
个实例:
instance ToJSON AB where
toJSON (A ab a) = object [ "ab" .= ab, "a" .= a ]
toJSON (B ab a) = object [ "ab" .= ab, "a" .= a ]
ab1 = A "foo" "bar"
ab2 = A "abc" "def"
*Main> import qualified Data.ByteString.Lazy.Char8 as LBS
*Main LBS> LBS.putStrLn $ encode ab2
{"ab":"abc","a":"def"}
*Main LBS> LBS.putStrLn $ encode ab1
{"ab":"foo","a":"bar"}
答案 2 :(得分:2)
一种hacky方式是简单地从结果对象中删除tag
:
{-# 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"
但是,当通用实例不可避免地发生变化时,它可能会回来咬你,所以如果你这样做,就要意识到你选择承担的技术债务。