2016-04-25 17 views
1

Ich versuche, ein JSON-Objekt zu analysieren, die durch folgendes „Modellschema“ beschrieben wird: (. Genommen vom API documentation direkt)Gibt es eine saubere Möglichkeit, Informationen beizubehalten, während ein JSON-Objekt mit Aeson ausgepackt wird?

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

Ich versuche Aeson zu verwenden, zu analysieren dies in der folgenden Art:

data Org = Org { active :: Bool 
       , orgId :: Text 
       , description :: Maybe Text 
       , reference :: Maybe Text 
       , version :: Int 
       } deriving (Show, Eq) 

ich habe soweit:

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 

Diese Implementierung funktioniert so lange, wie der JSON konsumiert ist als "active_org" markiert, aber natürlich fehlschlägt, wenn ein "archived_org" bereitgestellt wird. Wie verallgemeinere ich, um beide Fälle abzudecken, und ändere das erste Argument des Wertkonstruktors Org, je nachdem, ob es sich um einen "aktiven_org" oder einen "archivierten_org" handelt?

+2

Verwenden Sie die 'Alternative' /' MonadPlus' Instanzen von 'Parser':' (v. "Active_org") <|> (v.: "Archived_org") '. Wenn Sie benötigen, können Sie sagen, welcher Zweig mit z. '((True)) <$> (v.:" Active_org ")) <|> ((False,) <$> (v.:" Archived_org "))'. – user2407038

+0

@ user2407038 Wenn Sie das als Antwort schreiben möchten, würde ich es gerne akzeptieren. –

Antwort

3

Von einem ausgezeichneten Kommentar von @ user2407038, ich habe es mit der Arbeit folgende:

{-# 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