我正在尝试用aeson解析以下JSON。
{
"data": [
{
"id": "34",
"type": "link",
"story": "foo"
},
{
"id": "35",
"type": "link",
"story": "bar"
}
]
}
由于我想忽略很多字段,所以似乎I should use GHC generics。但是如何编写使用Haskell关键字的数据类型定义,如data
和type
?以下当然是:parse error on input `data'
data Feed = Feed {data :: [Post]}
deriving (Show, Generic)
data Post = Post {
id :: String,
type :: String,
story :: String
}
deriving (Show, Generic)
答案 0 :(得分:13)
您可以编写自己的FromJSON
和ToJSON
实例,而无需依赖GHC.Generics。这也意味着您可以为数据表示和JSON表示使用不同的字段名称。
Post的示例实例:
{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative
import Data.Aeson
import qualified Data.ByteString.Lazy as LBS
data Post = Post {
postId :: String,
typ :: String,
story :: String
}
deriving (Show)
instance FromJSON Post where
parseJSON (Object x) = Post <$> x .: "id" <*> x.: "type" <*> x .: "story"
parseJSON _ = fail "Expected an Object"
instance ToJSON Post where
toJSON post = object
[ "id" .= postId post
, "type" .= typ post
, "story" .= story post
]
main :: IO ()
main = do
print $ (decode $ Post "{\"type\": \"myType\", \"story\": \"Really interresting story\", \"id\" : \"SomeId\"}" :: Maybe Post)
LBS.putStrLn $ encode $ Post "myId" "myType" "Some other story"
Feed也可以这样做。如果您不必忽略字段,也可以使用deriveJSON
中的Data.Aeson.TH
,{{1}}采用函数修改字段名称作为第一个参数。
答案 1 :(得分:0)
要将@bennofs 方法与泛型结合起来,您可以参考 Aeson: the tutorial 中的示例:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Data.Aeson
import Data.Aeson.Types
data Person = Person {
_name :: String,
_age :: Int }
deriving (Generic)
instance ToJSON Person where
toJSON = genericToJSON defaultOptions {
fieldLabelModifier = drop 1 }
instance FromJSON Person where
parseJSON = genericParseJSON defaultOptions {
fieldLabelModifier = drop 1 }
同时将 fieldLabelModifier
设置为仅替换所需的标签:
keywordFieldLabelModifier "_id" = "id"
keywordFieldLabelModifier "_type" = "type"
keywordFieldLabelModifier = id