2013-08-23 113 views
10

我试图用aeson解析下面的JSON。解析包含保留关键字的字段名的JSON

{ 
    "data": [ 
     { 
      "id": "34", 
      "type": "link", 
      "story": "foo" 
     }, 
     { 
      "id": "35", 
      "type": "link", 
      "story": "bar" 
     } 
    ] 
} 

因为有很多领域我想忽略,似乎I should use GHC generics。但是如何编写一个使用Haskell关键字的数据类型定义,如datatype?当然,以下给出: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) 

回答

13

您可以编写自己的FromJSONToJSON情况下,不依赖于GHC.Generics。这也意味着您可以对数据表示形式和JSON表示使用不同的字段名称。对邮政

实施例的实例:

{-# 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" 

同样可以为进料来完成。如果您不必忽略字段,则还可以使用Data.Aeson.TH中的deriveJSON,该函数使用函数将字段名称修改为第一个参数。

+0

谢谢,很好用!将这种方法与“Generic”结合起来也是可能的吗?比如说'Post'类型没有'type'属性,看起来我无法手动执行'Feed'的'parseJSON'时导出派生(Generic)',然后将它们组合在问题中。 – mb21

+0

最后,我想知道我是否真的需要'Feed'数据类型,只是为了摆脱JSON中的'data'属性,或者我是否能够以某种方式直接获取帖子。 – mb21

+1

@ mb21 [a]具有FromJSON/ToJSON实例,所以如果你想要做的就是序列化一个Posts列表,直接用'encode listOfPosts'来完成。您可以将此方法与Generic结合使用,只需使用Generic为任何其他实例派生Post实例,然后手动为Feed编写实例。它只是工作。 – bennofs

相关问题