Reputation: 23
the following code makes an api call in yesod. the question is how do i "cast" the resulting object to a predefined haskell type?
Network.HTTP.Conduit.withManager $ \manager -> do
response <- http req manager
resBody <- responseBody response C.$$+- sinkParser json
liftIO $ putStrLn $ T.pack (show resBody)
example output log
Object (fromList [("val1",Number 1.0),("val2",String "text")])
all the attempts i have made to decode with Aeson or fromJSON are failing.
much appreciated
yunis
Upvotes: 1
Views: 120
Reputation: 53695
Where the value came from doesn't seem to matter. You've got a hold of a piece of data with type Aeson.Value
, so you just have to figure out how to succeed in your attempts with fromJSON.
Here's a bit of code adapted from the docs for the FromJSON class
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Aeson as Aeson
import qualified Data.HashMap.Strict as HashMap
import Data.Aeson ((.:))
import Data.Text (Text)
-- this is the data you already have, which you named resBody
resBody :: Aeson.Value
resBody = Aeson.Object $
HashMap.fromList
[ ("val1", Aeson.Number 1.0)
, ("val2", Aeson.String "text")]
-- Step 1: create a custom Haskell data type to house the data.
-- I named it Coord to match the example code from the link above,
-- but you should probably give it a more meaningful name.
data Coord = Coord { x :: Double, y :: Text }
deriving (Show)
-- Step 2: write a FromJSON instance for your custom data type.
-- In this case, it is almost identical to the example code in the docs.
instance Aeson.FromJSON Coord where
parseJSON = Aeson.withObject "Coord" $ \v -> Coord
<$> v .: "val1"
<*> v .: "val2"
Giving it a spin in the repl
ghci> -- Here's our data
ghci> resBody
Object (fromList [("val1",Number 1.0),("val2",String "text")])
ghci> -- Next, we decode using fromJSON, annotating the result as our desired type
ghci> Aeson.fromJSON resBody :: Aeson.Result Coord
Success (Coord {x = 1.0, y = "text"})
Upvotes: 2