2014-03-31 46 views
2

我需要解析不具有嚴格的結構JSON API響應:埃宋解析動態對象

{ 
response: { /* any object here */ } 
} 

怎麼可能寫出parseResponse將離開解析能力(或爲它選擇一個分析器)供以後使用?

我最後一次嘗試如下。我不喜歡它,因爲它不允許選擇響應類型,如Aeson的decode所做的那樣。

data APIResponse = 
    APIResponse { response :: Value } deriving (Show,Generic) 

instance FromJSON APIResponse 

parseResponse :: BC.ByteString -> Either String Value 
parseResponse resp = 
    case eitherDecode . BLC.fromStrict $ resp of 
    Right x -> Right $ response x 
    Left msg -> Left msg 

回答

7

我喜歡把埃宋的在兩個不同的步驟,從ByteString -> Value解析和FromJSON a => Value -> a映射發生。如果您不知道正確的映射是什麼,那麼您可以簡單地解析爲Value。稍後在運行時,當您決定正確的映射時,您可以稍後再做。

import qualified Data.HashMap.Strict as Hm 

decodeResponse :: ByteString -> Either String Value 
decodeResponse bs = do 
    val <- eitherDecode bs 
    case val of 
    Object o -> case Hm.lookup "response" o of 
        Nothing -> fail "Invalid structure, missing 'response' key" 
        Just resp -> return resp 
    _ -> fail "Invalid structure, expected an object" 

爲了不解析執行映射,到Value轉換爲FromJSON a => a,您使用parse/parseEither/parseMaybe家族和parseJSON

mapValue :: FromJSON a => Value -> Either String a 
mapValue = parseString parseJSON 
+0

大運行產生的解析器,謝謝!請問我可以指點Data.Aeson的文檔是否應該查找將Value轉換爲Array [Value]的方法? –

+1

查看'parse' /'parseMaybe' /'parseEither'系列。具體的部分是[解碼混合類型對象](http://hackage.haskell.org/package/aeson-0.7.0.2/docs/Data-Aeson.html)。你也可以在'Value'上模式匹配,並使用'vector'操作來解開'Array'。 –