如何处理Haskell请求中的HttpResponseBody?

How to process HttpResponseBody in Haskell req?

我有一个从 API 获得 JSON 响应的应用程序,我正在尝试从该响应中获得特定的密钥。工作代码如下所示:

{-# LANGUAGE OverloadedStrings #-}

module Main (main) where
import Data.Aeson
import Network.HTTP.Req
   
tinyUIDRequest :: String -> Req (JsonResponse Object)
tinyUIDRequest url = let payload = object [ "url" .= url ] 
                 in req 
                    POST 
                    (https "tinyuid.com" /: "api" /: "v1" /: "shorten") (
                    ReqBodyJson payload) 
                    jsonResponse
                    mempty           

main :: IO ()
main = do 
    response <- runReq defaultHttpConfig (tinyUIDRequest "http://google.com")
    let body = responseBody response
    print body

处理响应的函数应该类似于:

tinyUIDResponseHandler :: HttpResponseBody (JsonResponse Object) -> String
tinyUIDResponseHandler r = case lookup "result_url" r of 
                            Just url -> url
                            Nothing -> ""

不幸的是,我无法弄清楚如何将 HttpResponseBody (JsonResponse Object) 转换为 hashmap/list 之类的东西并找到合适的密钥。我正在检查 the documentation and req source code 但也许,作为 Haskell 的初学者,我不知道究竟要寻找什么来理解响应类型的内部结构。

HttpResponseBody 是一个转移注意力的问题。它是一个关联类型,HttpResponseBody (JsonResponse a)a 相同,因此 HttpResponseBody (JsonResponse Object) 实际上只是 Object。因此,一旦您有了 bodyreq 的工作就完成了,现在您只需要关心 aeson

由于 body 是一个 Object 而不是元组列表,您不能在其上使用 Prelude 的 lookup。如果你的 Aeson 版本早于 2,那么 Object 就是 HashMap Text Value,所以这样做:

import Data.Text
import qualified Data.HashMap.Strict as HM

tinyUIDResponseHandler :: Object -> Text
tinyUIDResponseHandler r = case HM.lookup "result_url" r of 
                            Just (String url) -> url
                            _ -> ""

如果您的 Aeson 版本是 2 或更高版本,则 ObjectKeyMap Value,因此请改为:

import Data.Text
import qualified Data.Aeson.KeyMap as AKM

tinyUIDResponseHandler :: Object -> Text
tinyUIDResponseHandler r = case AKM.lookup "result_url" r of 
                            Just (String url) -> url
                            _ -> ""

在任何一种情况下,tinyUIDResponseHandler body 都是您想要的值,例如,您可以 print (tinyUIDResponseHandler body).