AESON:解析动态结构

时间:2017-07-03 09:58:53

标签: json haskell aeson

我有像这样的JSON结构

{
  "tag1": 1,
  "tag2": 7,
  ...
}

我有这样的类型

data TagResult { name :: String, numberOfDevicesTagged :: Int } deriving (Show, Eq)
newtype TagResultList = TagResultList { tags :: [TagResult] }

标签名称当然是完全动态的,我在编译时不知道它们。 我想创建一个实例FromJSON来解析JSON数据,但我不能让它编译。<​​/ p>

如何定义parseJSON来实现这一目标?

1 个答案:

答案 0 :(得分:1)

您可以使用Object是HasMap的事实,并在运行时提取密钥。然后,您可以按如下方式编写FromJSON实例 -

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
    myIndex = indexPath.row

    if let vc = storyboard?.instantiateViewController(withIdentifier: storyboardIds[myIndex]) {

        self.navigationController?.pushViewController(vc, animated: true)
    }
}

上述程序应打印标签结果列表。

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