json-api: Utilities for generating JSON-API payloads

This is a package candidate release! Here you can preview how this package release will appear once published to the main package index (which can be accomplished via the 'maintain' link below). Please note that once a package has been published to the main package index it cannot be undone! Please consult the package uploading documentation for more information.

[maintain] [Publish]

Provides utilities for deriving JSON payloads conformant to the json-api specification


[Skip to Readme]

Properties

Versions 0.1.0.0, 0.1.0.1, 0.1.0.2, 0.1.0.3, 0.1.0.4, 0.1.1.0, 0.1.1.1, 0.1.1.2, 0.1.1.2, 0.1.2.0, 0.1.3.0, 0.1.4.0
Change log None available
Dependencies aeson (>=0.11.2.0 && <0.11.3.0), base (>=4.7 && <5.0), containers (>=0.5.7.1 && <0.5.8.0), data-default (>=0.5.3 && <5.6.0), lens (>=4.13 && <5.0), lens-aeson (>=1.0.0.5 && <1.0.1.0), text (>=1.2.2.1 && <1.2.3.0), unordered-containers (>=0.2.7.1 && <0.2.8.0), url (>=2.1.3 && <2.2.0) [details]
License MIT
Copyright 2016 Todd Mohney
Author Todd Mohney
Maintainer Todd Mohney <toddmohney@gmail.com>
Category Network
Home page https://github.com/toddmohney/json-api
Bug tracker https://github.com/toddmohney/json-api/issues
Source repo head: git clone https://github.com/toddmohney/json-api.git
head: git clone https://github.com/toddmohney/json-api
Uploaded by toddmohney at 2017-01-07T21:06:10Z

Modules

[Index]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


Readme for json-api-0.1.1.2

[back to package description]

Circle CI

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 principles make JSON-API an attractive resource serialization option.

The specification

Find the specification here

Example usage

Let's start with an example User record:

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 like so:

-- 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:

{
  "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 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 illustrating how the library can be used in the context of a web server.

Hackage

Module documentation can be found on Hackage