在使用 Aeson 展开 JSON 对象时,是否有一种干净的方法来保留信息?

Is there a clean way to retain information while unwrapping a JSON object with 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 值构造函数?

从 @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