Json 如何在无标记的Aeson中序列化记录和数据类型?
例如,我有多个构造函数的数据类型Json 如何在无标记的Aeson中序列化记录和数据类型?,json,haskell,aeson,Json,Haskell,Aeson,例如,我有多个构造函数的数据类型 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" } 我知道可以使用来操纵构造函数的处理方式,但找不到我想要的 在序
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"
}
我知道可以使用来操纵构造函数的处理方式,但找不到我想要的
在序列化的JSON中是否有可能省略
标记字段?我只需要单向序列化(没有理由让它去反序列化),但是数据类型非常大,无法编写如何手动序列化它。只需自己定义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"}
一种简单的方法是从结果对象中删除标记
:
{-# 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"
但是,当通用实例不可避免地发生变化时,它可能会反过来咬你,因此如果你这样做,请注意你选择承担的技术债务。有一个字段,并将其设置为
将其设置为UntagedValue
(从,在aeson-1.0.0和更高版本中提供)应该可以满足您的需要。由于相对较多的属性(其中一些可能是
,一些是嵌套的)和构造函数数量,我希望避免编写代码来手动序列化它。但如果没有其他选择,我会选择it@klappvisor只要每个字段的类型是一个ToJSON
实例,@DanielWagner我使用defaultOptions{ommitnothingfields=True}
因此,如果我想省略它们,我想我必须这样做。我想最好还是接受它,等待或贡献给Aeson。那个黑客正是我要找的。谢谢举个例子,我认为这是序列化和反序列化在没有标记的情况下工作所需的最少代码:data Foo=FooA{x::Int}| FooB{y::Int}派生(Generic,Show);实例ToJSON Foo,其中toEncoding=genericToEncoding(defaultOptions{sumcodeding=untagedvalue});实例FromJSON Foo,其中parseJSON=genericParseJSON(defaultOptions{sumEncoding=UntagedValue});