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
4

1 回答 1

7

我喜欢认为 Aeson 发生在两个不同的步骤中,解析 fromByteString -> Value和映射 from FromJSON a => Value -> a。如果您不立即知道正确的映射是什么,您可以简单地解析为 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"

要在没有解析的情况下执行映射,要将 a 转换Value为 a FromJSON a => a,请使用parse//parseEither系列parseMaybe并运行由生成的解析器parseJSON

mapValue :: FromJSON a => Value -> Either String a
mapValue = parseString parseJSON
于 2014-03-31T16:37:43.243 回答