Reputation: 1965
I have an application that gets JSON response from an API and I'm trying to get a specific key from that response. The working code looks as below:
{-# 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
And the function to process the response should look similar to:
tinyUIDResponseHandler :: HttpResponseBody (JsonResponse Object) -> String
tinyUIDResponseHandler r = case lookup "result_url" r of
Just url -> url
Nothing -> ""
unfortunately I'm not able to figure out how to transform HttpResponseBody (JsonResponse Object)
to something like hashmap/list and find a proper key. I was checking the documentation and req source code but maybe, as a beginner in Haskell, I don't know exactly what to look for to understand the internals of the response type.
Upvotes: 0
Views: 303
Reputation: 48602
HttpResponseBody
is a red herring. It's an associated type, and HttpResponseBody (JsonResponse a)
is the same as just a
, so HttpResponseBody (JsonResponse Object)
is really just Object
. As such, once you have body
, req
's job is done, and it's now just aeson
that you need to be concerned with.
Since body
is an Object
and not a list of tuples, you can't use Prelude's lookup
on it. If your Aeson version is older than 2, then Object
is just HashMap Text Value
, so do this instead:
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
_ -> ""
If your Aeson version is 2 or newer, then Object
is KeyMap Value
, so do this instead:
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
_ -> ""
In either case, tinyUIDResponseHandler body
will then be the value you want, so for example, you could do print (tinyUIDResponseHandler body)
.
Upvotes: 4