Post requests with PureScript Affjax and Argonaut


In this post I will explain how make a simple ajax call in PureScript, using Affjax and Argonaut.

For this example I’m going to use http://jsonplaceholder.typicode.com/ as my API endpoints. We will make a POST call to the /posts endpoint to create a new post.

A post has these fields: title, body, userId and id. To create a new one, we’ll have to send an object containing the first three fields to the appropriate endpoint.

We can model our data type:

data Post = Post { id :: Maybe Int
                 , title :: String
                 , body :: String
                 , userId :: Int
                 }
                 
post1 = Post { id: Nothing, title: "title", body: "body", userId: 20 }

We have our data, now we only need to find out how to send it to our endpoint! Affjax documentation tells us that:

When sending data in a request the Requestable class enables automatic conversion into a format that is acceptable for an XHR request. Correspondingly there is a Respondable class for reading data that comes back from the server.

We need to implement a Respondable and a Requestable instance for our data type. The documentation doesn’t tell us much more, and the type signatures are a little cryptic for a beginner.

Luckily, the instances are already defined for Json, so we can look at Argonaut for rescue!

We will need to implement decodeJson and encodeJson for our data type.

instance decodeJsonPost :: DecodeJson Post where
  decodeJson json = do
    obj <- decodeJson json
    id <- obj .? "id"
    title <- obj .? "title"
    body <- obj .? "body"
    userId <- obj .? "userId"
    pure $ Post { id, title, body, userId }

instance encodeJsonPost :: EncodeJson Post where
  encodeJson (Post post)
    = "id" := post.id
    ~> "title" := post.title
    ~> "body" := post.body
    ~> "userId" := post.userId
    ~> jsonEmptyObject

Now we’re ready to make our ajax call:

main :: forall e. Eff (err :: EXCEPTION, ajax :: AJAX, console :: CONSOLE | e) Unit
main = void $ launchAff $ do
  res <- post "http://jsonplaceholder.typicode.com/posts" (encodeJson post1)
  liftEff $ log $ "response: " <> res.response

Related Posts

Adding static files to Yesod

Planning a simple Reddit clone with Yesod

React-router-dom bindings for Reason

Parsing complex foreign objects in PureScript

A way to deal with big objects and FFI.

Functor, Applicative e Monad illustrati

Una guida chiara

Arbitrary length lists with QuickCheck

Using sized to build arbitrary length lists for QuickCheck

PureScript Impressions

Trying to put some sense in JavaScript

Clojure Examples

Toggling DELL 9350's touchpad on Ubuntu 15.10

How to set up a hotkey to toggle DELL 9350's touchpad on Ubuntu 15.10

Using the Asus MB168B+ with Ubuntu 15.10

How to edit the driver install script to make it work on Ubuntu 15.10+ (and other distros)