在用Aeson解包JSON对象时是否有一种干净的方法来保留信息?

时间:2016-04-25 16:26:16

标签: json haskell aeson

我正在尝试解析JSON对象,该对象由以下“模型架构”描述:

{
  "(archived|active)_org": {
    "id": "",
    "description": "",
    "reference": "",
    "bucket_name": "",
    "version": 0
  }
}

(直接来自API documentation。)

我正在尝试使用Aeson将其解析为以下类型:

data Org = Org { active :: Bool
               , orgId :: Text
               , description :: Maybe Text
               , reference :: Maybe Text
               , version :: Int
               } deriving (Show, Eq)

我得到了这个:

instance FromJSON Org where
  parseJSON (Object v) = do
    Just (Object v') <- v .: "active_org"
    orgId <- v' .: "id"
    description <- v' .:? "description"
    reference <- v' .:? "reference"
    version <- v' .: "version"
    return $ Org True orgId description reference version
  parseJSON _ = mzero

只要消耗的JSON被标记为“active_org”,该实现就会起作用,但如果提供“archived_org”,当然会失败。如何概括以涵盖这两种情况,并根据它是“active_org”还是“archived_org”将第一个参数更改为Org值构造函数?

1 个答案:

答案 0 :(得分:3)

根据@ user2407038的优秀评论,我得到了以下内容:

{-# LANGUAGE TupleSections #-}

instance FromJSON Org where
  parseJSON (Object v) = ((True,) <$> (v .: "active_org"))
                     <|> ((False,) <$> (v .: "archived_org"))
                     >>= inner
    where inner (b, Object v') = Org b
                             <$> v' .: "id"
                             <*> v' .:? "description"
                             <*> v' .:? "reference"
                             <*> v' .: "version"
          inner (_, _) = mzero
  parseJSON _ = mzero