What ?
A simple project showing how to make calls to an API and parsing JSON using HTTP Conduit and Aeson.
Why ?
Because JSON is very popular and use it with Haskell is really cool.
How ?
Here you have the sample code from basic GET calls to sending JSON via POST using httpbin.org as a reference:
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Network.HTTP.Simple
-- SIMPLE GET
simpleGet :: IO ()
simpleGet = do
response <- httpLbs "http://httpbin.org/get"
print (getResponseBody response)
-- CUSTOM REQUEST
request = setRequestMethod "GET"
$ setRequestHost "httpbin.org"
$ setRequestPath "/get"
$ defaultRequest
customRequest :: IO ()
customRequest = do
response <- httpLbs request
print (getResponseBody response)
-- SIMPLE HTTPS GET
simpleHttpsGet :: IO ()
simpleHttpsGet = do
response <- httpLbs "https://httpbin.org/get"
print (getResponseBody response)
-- CUSTOM HTTPS REQUEST
httpsRequest = setRequestMethod "GET"
$ setRequestHost "httpbin.org"
$ setRequestPath "/get"
$ setRequestSecure True
$ setRequestPort 443
$ defaultRequest
customHttpsRequest :: IO ()
customHttpsRequest = do
response <- httpLbs httpsRequest
print (getResponseBody response)
-- GENERIC JSON GET
genericJsonGet :: IO ()
genericJsonGet = do
response <- httpJSON "http://httpbin.org/get" :: IO (Response Value)
print (getResponseBody response)
-- PARSED JSON GET
data CallInfo = CallInfo String String
instance FromJSON CallInfo where
parseJSON (Object v) = do
origin <- v .: "origin"
url <- v .: "url"
return (CallInfo origin url)
parsedJsonGet :: IO ()
parsedJsonGet = do
response <- httpJSON "http://httpbin.org/get" :: IO (Response CallInfo)
case getResponseBody response of
CallInfo origin url ->
print ("Requesting " ++ url ++ " from " ++ origin)
-- SIMPLE POST
simplePost :: IO ()
simplePost = do
response <- httpLbs "POST http://httpbin.org/post"
print (getResponseBody response)
-- GENERIC JSON POST
genericJsonPost :: IO ()
genericJsonPost = do
response <- httpJSON "POST http://httpbin.org/post" :: IO (Response Value)
print (getResponseBody response)
-- PARSED JSON POST
data User = User String String
instance ToJSON User where
toJSON (User email fullname) = object
[ "email" .= email
, "fullname" .= fullname ]
parsedJsonPost :: IO ()
parsedJsonPost = do
let user = User "test@test.com" "Test User"
let request = setRequestBodyJSON user "POST http://httpbin.org/post"
response <- httpJSON request :: IO (Response Value)
print (getResponseBody response)
-- MAIN
main :: IO ()
main = do
simpleGet
customRequest
simpleHttpsGet
customHttpsRequest
genericJsonGet
parsedJsonGet
simplePost
genericJsonPost
parsedJsonPost
Try it at home
For build and run the code you may clone the repo https://github.com/csaltos/hello-conduit and run these commands:
cd hello-conduit
cabal build
cabal exec -- hello-conduit
You can also use the interpreter with the following commands:
cabal install --lib aeson
cabal install --lib http-conduit
cd hello-conduit
ghci app/Main.hs
And then inside the interpreter you may run:
:set -XOverloadedStrings
parsedJsonGet
And of course you can call the other samples, makes changes, reload and try and learn new things.
Who ?
This sample is based on the tutorials at https://github.com/snoyberg/http-client/blob/master/TUTORIAL.md and https://www.fpcomplete.com/haskell/library/aeson/
Some documentation can be found at https://hackage.haskell.org/package/http-conduit-2.3.8/docs/Network-HTTP-Simple.html and https://hackage.haskell.org/package/aeson-0.11.1.0/docs/Data-Aeson.html
Top comments (2)
Thanks Carlos.
Nice cheatsheet!
Let me add one tutorial. I found it very helpful to understand Aeson inner workings.
Aeson tutorial