2016-04-25 43 views
1

我試圖解析這是由下面的「模型模式」中描述的JSON對象:(直接從API documentation兩者)​​有沒有一種乾淨的方式來保留信息,同時解開Aeson的JSON對象?

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

我試圖用埃宋解析這爲以下類型:

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」?

+2

使用'Alternative' /'MonadPlus' Parser'的'實例:'(V: 「active_org」) <|>(v:「archived_org」)'。如果你需要,你可以知道哪個分支是用例如((True)<$>(v:「active_org」))<|>((False)<$>(v:「archived_org」))'。 – user2407038

+0

@ user2407038如果你想把它寫成答案,我會高興地接受它。 –

回答

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 
相關問題