Есть ли чистый способ сохранить информацию при развертывании объекта 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
Другие вопросы по тегам