AESON:解析动态结构
AESON: Parse dynamic structure
我有一个这样的JSON结构
{
"tag1": 1,
"tag2": 7,
...
}
我有这样的类型
data TagResult { name :: String, numberOfDevicesTagged :: Int } deriving (Show, Eq)
newtype TagResultList = TagResultList { tags :: [TagResult] }
标签名称当然是完全动态的,我在编译时不知道它们。
我想创建一个实例 FromJSON
来解析 JSON 数据,但我无法编译它。
如何定义 parseJSON
来实现这一点?
您可以利用 Object 是 HasMap 的事实并在运行时提取密钥。然后,您可以按如下方式编写 FromJSON 实例 -
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Aeson
import qualified Data.Text as T
import qualified Data.HashMap.Lazy as HashMap
data TagResult = TagResult { name :: String
, numberOfDevicesTagged :: Int
} deriving (Show, Eq)
newtype TagResultList = TagResultList { tags :: [TagResult] } deriving Show
instance ToJSON TagResult where
toJSON (TagResult tag ntag) =
object [ T.pack tag .= ntag ]
instance ToJSON TagResultList where
toJSON (TagResultList tags) =
object [ "tagresults" .= toJSON tags ]
instance FromJSON TagResult where
parseJSON (Object v) =
let (k, _) = head (HashMap.toList v)
in TagResult (T.unpack k) <$> v .: k
parseJSON _ = fail "Invalid JSON type"
instance FromJSON TagResultList where
parseJSON (Object v) =
TagResultList <$> v .: "tagresults"
main :: IO ()
main = do
let tag1 = TagResult "tag1" 1
tag2 = TagResult "tag2" 7
taglist = TagResultList [tag1, tag2]
let encoded = encode taglist
decoded = decode encoded :: Maybe TagResultList
print decoded
上面的程序应该打印标签结果列表。
Just (TagResultList {tags = [TagResult {name = "tag1", numberOfDevicesTagged = 1},TagResult {name = "tag2", numberOfDevicesTagged = 7}]})
我有一个这样的JSON结构
{
"tag1": 1,
"tag2": 7,
...
}
我有这样的类型
data TagResult { name :: String, numberOfDevicesTagged :: Int } deriving (Show, Eq)
newtype TagResultList = TagResultList { tags :: [TagResult] }
标签名称当然是完全动态的,我在编译时不知道它们。
我想创建一个实例 FromJSON
来解析 JSON 数据,但我无法编译它。
如何定义 parseJSON
来实现这一点?
您可以利用 Object 是 HasMap 的事实并在运行时提取密钥。然后,您可以按如下方式编写 FromJSON 实例 -
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Aeson
import qualified Data.Text as T
import qualified Data.HashMap.Lazy as HashMap
data TagResult = TagResult { name :: String
, numberOfDevicesTagged :: Int
} deriving (Show, Eq)
newtype TagResultList = TagResultList { tags :: [TagResult] } deriving Show
instance ToJSON TagResult where
toJSON (TagResult tag ntag) =
object [ T.pack tag .= ntag ]
instance ToJSON TagResultList where
toJSON (TagResultList tags) =
object [ "tagresults" .= toJSON tags ]
instance FromJSON TagResult where
parseJSON (Object v) =
let (k, _) = head (HashMap.toList v)
in TagResult (T.unpack k) <$> v .: k
parseJSON _ = fail "Invalid JSON type"
instance FromJSON TagResultList where
parseJSON (Object v) =
TagResultList <$> v .: "tagresults"
main :: IO ()
main = do
let tag1 = TagResult "tag1" 1
tag2 = TagResult "tag2" 7
taglist = TagResultList [tag1, tag2]
let encoded = encode taglist
decoded = decode encoded :: Maybe TagResultList
print decoded
上面的程序应该打印标签结果列表。
Just (TagResultList {tags = [TagResult {name = "tag1", numberOfDevicesTagged = 1},TagResult {name = "tag2", numberOfDevicesTagged = 7}]})