Aeson解析动态对象

时间:2014-03-31 16:22:14

标签: haskell aeson

我需要解析没有严格结构的json API响应:

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

如何编写parseResponse能够解析(或选择Parser)以供以后使用?

我的最后一次尝试如下。我不喜欢它,因为它不允许像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

1 个答案:

答案 0 :(得分:7)

我喜欢将Aeson视为两个截然不同的步骤,即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