Есть ли чистый способ сохранить информацию при развертывании объекта JSON с помощью Aeson?
Я пытаюсь проанализировать объект JSON, который описывается следующей "схемой модели":
{
"(archived|active)_org": {
"id": "",
"description": "",
"reference": "",
"bucket_name": "",
"version": 0
}
}
(Взято непосредственно из документации API.)
Я пытаюсь использовать 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". Как обобщить, чтобы охватить оба случая, и заменить первый аргумент на Org
Значение конструктора в зависимости от того, является ли он "active_org" или "archived_org"?
1 ответ
Решение
Из превосходного комментария @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