DEV Community

Carlos Saltos
Carlos Saltos

Posted on

API JSON calls with Haskell

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

And then inside the interpreter you may run:

:set -XOverloadedStrings

parsedJsonGet
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
jonbaldie profile image
Jonathan Baldie

Thanks Carlos.

Collapse
 
fabfianda_31 profile image
fabfianda

Nice cheatsheet!

Let me add one tutorial. I found it very helpful to understand Aeson inner workings.

Aeson tutorial