2016-04-25 46 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 
相关问题