我是 Haskell 的新手,来自命令式编程背景。我希望能够以“Haskell 方式”将对象序列化为 JSON,但还不太确定如何做到这一点。
我已经阅读了 RealWorldHaskell 的第 5 章,其中谈到了一些关于 JSON 的内容,并与 Aeson 一起玩过。我还查看了一些用 Haskell 编写的 JSON API 库,例如:
这让我能够从对象创建非常基本的 JSON 字符串(也感谢这篇博文):
{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
import Data.Aeson
import GHC.Generics
data User = User {
email :: String,
name :: String
} deriving (Show, Generic)
instance ToJSON User
main = do
let user = User "foo@example.com" "Hello World"
let json = encode user
putStrLn $ show json
那将打印出:
"{\"email\":\"foo@example.com",\"name\":\"Hello World\"}"
现在的目标是,将另一个字段添加到User
可以具有任意字段的实例中。Facebook Graph API 有一个名为 的字段data
,它是一个 JSON 对象,具有您想要的任何属性。例如,您可能会向 Facebook 的 API 发出这样的请求(伪代码,不熟悉 Facebook API):
POST api.facebook.com/actions
{
"name": "read",
"object": "book",
"data": {
"favoriteChapter": 10,
"hardcover": true
}
}
前两个字段 ,name
和object
是 type String
,而data
字段是任意属性的映射。
问题是,在上述User
模型上实现这一目标的“Haskell 方式”是什么?
我可以理解如何做简单的案例:
data User = User {
email :: String,
name :: String,
data :: CustomData
} deriving (Show, Generic)
data CustomData = CustomData {
favoriteColor :: String
}
但这并不是我想要的。这意味着User
当序列化为 JSON 时,该类型将始终如下所示:
{
"email": "",
"name": "",
"data": {
"favoriteColor": ""
}
}
问题是,你是如何做到的,所以你只需要定义User
一次该类型,然后可以将任意字段附加到该data
属性,同时仍然受益于静态类型(或任何接近该类型的东西,对细节不太熟悉类型呢)。