json-api-0.1.0.4: README.md
[](https://circleci.com/gh/toddmohney/json-api)
## Haskell Implementation of the JSON-API specification
#### Motivation
From the specification itself:
> If you’ve ever argued with your team about the way your JSON responses should
> be formatted, JSON API can be your anti-bikeshedding tool.
>
> By following shared conventions, you can increase productivity, take advantage
> of generalized tooling, and focus on what matters: your application.
>
> Clients built around JSON API are able to take advantage of its features around
> efficiently caching responses, sometimes eliminating network requests entirely.
All in all, API discoverability and other [HATEOAS](https://spring.io/understanding/HATEOAS)
principles make JSON-API an attractive resource serialization option.
#### The specification
Find the specification [here](http://jsonapi.org/)
#### Example usage
Let's start with an example User record:
```Haskell
data User = User
{ userId :: Int
, userFirstName :: String
, userLastName :: String
} deriving (Eq, Show)
$(deriveJSON defaultOptions ''User)
```
From this, we can use the `json-api` package to produce a payload conformant
to the [JSON-API specification](http://jsonapi.org/) like so:
```Haskell
-- Builds the Document which will be serialized as our
-- web server's response payload
mkDocument :: User -> Links -> Document User Text Int
mkDocument usr links =
Document
(Singleton $ toResource usr)
(Just links)
Nothing
-- Helper function to convert a User into a resource object
-- This could be our canonical serialization function for a User in any
-- response payload
toResource :: User -> Resource User Text
toResource user =
Resource resourceId resourceType user resourceLinks resourceMetaData
where
resourceId = ResourceId . pack . show . userId $ user
resourceType = ResourceType "User"
resourceLinks = Just $ userLinks user
resourceMetaData = Nothing
-- helper function to build links for a User resource
userLinks :: User -> Links
userLinks user = toLinks [ ("self", selfLink) ]
where
selfLink = toURL selfPath
selfPath = "/users/" <> (show $ userId user)
```
When delivered as a response from a web server, for example, we get a payload
that looks like this:
```JSON
{
"data":{
"attributes":{
"userFirstName":"Isaac",
"userLastName":"Newton",
"userId":1
},
"id":"1",
"meta":null,
"type":"User",
"links":{
"self":"/users/1"
}
},
"meta":null,
"links":{
"self":"/users/1"
}
}
```
Neat! We can see that if we would like the full User data for the User with
ID=1, we can query `/users/1`. Discoverability!
We can also see from the top-level `links` data that this particular payload originated
from `/users/1`.
This is a very simple example to provide an introduction to the basic idea
behind JSON-API and how to use this library. Check out [these examples](http://jsonapi.org/examples/)
for more robust representations of resourceful payloads. Here, you'll start to
see the more comprehensive benefits of a discoverable API.
#### Example Project
There is an [example project](https://github.com/toddmohney/json-api/tree/master/example) illustrating how the library can be used in the context of a web server.
#### Hackage
Module documentation can be found on [Hackage](http://hackage.haskell.org/package/json-api)