数据类型的默认翻译,例如:
data Media = Video { title :: Text }
| AudioBook { title :: Text }
deriving Generic
实际上非常接近你想要的。(为了示例的简单性,我定义ToJSON
了实例并对示例进行编码,以查看我们得到的 JSON 类型。)
aeson,默认
因此,使用我们拥有的默认实例(查看产生此输出的完整源文件):
[{"tag":"Video","title":"Some title"},{"tag":"AudioBook","title":"Other title"}]
让我们看看我们是否可以通过自定义选项更接近...
aeson, 定制tagFieldName
使用自定义选项:
mediaJSONOptions :: Options
mediaJSONOptions =
defaultOptions{ sumEncoding =
TaggedObject{ tagFieldName = "objectClass"
-- , contentsFieldName = undefined
}
}
instance ToJSON Media
where toJSON = genericToJSON mediaJSONOptions
我们得到:
[{"objectClass":"Video","title":"Some title"},{"objectClass":"AudioBook","title":"Other title"}]
(想想你自己想对实际代码中的未定义字段做什么。)
aeson, 定制constructorTagModifier
添加
, constructorTagModifier = fmap Char.toLower
给mediaJSONOptions
:
[{"objectClass":"video","title":"Some title"},{"objectClass":"audiobook","title":"Other title"}]
伟大的!正是你指定的!
解码
只需添加一个具有相同选项的实例即可从此格式解码:
instance FromJSON Media
where parseJSON = genericParseJSON mediaJSONOptions
例子:
*Main> encode example
"[{\"objectClass\":\"video\",\"title\":\"Some title\"},{\"objectClass\":\"audiobook\",\"title\":\"Other title\"}]"
*Main> decode $ fromString "[{\"objectClass\":\"video\",\"title\":\"Some title\"},{\"objectClass\":\"audiobook\",\"title\":\"Other title\"}]" :: Maybe [Media]
Just [Video {title = "Some title"},AudioBook {title = "Other title"}]
*Main>
完整的源文件。
通用 aeson,默认
为了获得更完整的画面,让我们也看看generic-aeson
会提供什么包(在hackage)。它也有很好的默认翻译,在某些方面与aeson
.
正在做
import Generics.Generic.Aeson -- from generic-aeson package
并定义:
instance ToJSON Media
where toJSON = gtoJson
给出结果:
[{"video":{"title":"Some title"}},{"audioBook":{"title":"Other title"}}]
因此,它与我们在使用aeson
.
generic-aeson 的选项(设置)对我们来说并不有趣(它们只允许去除前缀)。
(完整的源文件。)
aeson,ObjectWithSingleField
除了小写构造函数名称的第一个字母之外,generic-aeson
的翻译似乎类似于 中可用的选项aeson
:
让我们试试这个:
mediaJSONOptions =
defaultOptions{ sumEncoding = ObjectWithSingleField
, constructorTagModifier = fmap Char.toLower
}
是的,结果是:
[{"video":{"title":"Some title"}},{"audiobook":{"title":"Other title"}}]
其余选项:(aeson, TwoElemArray
)
上面没有考虑一个可用的选项,因为sumEncoding
它提供了一个与所询问的 JSON 表示不太相似的数组。是TwoElemArray
。例子:
[["video",{"title":"Some title"}],["audiobook",{"title":"Other title"}]]
是(谁)给的:
mediaJSONOptions =
defaultOptions{ sumEncoding = TwoElemArray
, constructorTagModifier = fmap Char.toLower
}