View Source JSON:API library for Plug and Phoenix applications

Server library to build JSON:API compliant REST APIs.

json-api-support

JSON:API Support

This library currently implements version 1.0 of the JSON:API specification.

documentation

Documentation

quickstart

Quickstart

installation

Installation

Add the following line to your mix.deps file with the desired version to install jsonapi_plug.

defp deps do [
  ...
  {:jsonapi_plug, "~> 1.0"}
  ...
]

configuration

Configuration

You start by declaring one or more APIs. APIs are collections of endpoints that share a common configuration:

defmodule MyApp.API do
  use JSONAPIPlug.API, otp_app: :my_app
end

See the JSONAPIPlug.API module documentation to learn how to customize your APIs via application configuration of your app.

receiving-requests

Receiving requests

In order to parse JSON:API requests from clients you need to add the JSONAPIPlug.Plug plug to each of your plug pipelines or phoenix controllers handling requests for a specific resource:

defmodule MyApp.PostsController do
  ...
  plug JSONAPIPlug.Plug, api: MyApp.API, resource: MyApp.PostResource
  ...
end

This will take care of ensuring JSON:API specification compliance and will return errors for invalid requests.

The :api option expects a module using JSONAPI.API for configuration.

The :resource option expects a module using JSONAPIPlug.Resource to convert to/from JSON:API format.

When requests are processed, the :jsonapi_plug connection private field is populated with the parsed request.

See the JSONAPIPlug.Plug module documentation for usage and options.

serving-responses

Serving responses

To start serving responses, you need to have some data to return to clients:

defmodule MyApp.Post do
  @type t :: %__MODULE__{id: pos_integer(), body: String.t(), title: String.t()}

  @enforce_keys [:id, :body, :title]
  defstruct [:id, :body, :title]
end

and define a resource module to render your resource:

defmodule MyApp.PostResource do
  use JSONAPIPlug.Resource,
    type: "post",
    attributes: [
      title: nil,
      text: nil,
      excerpt: [serialize: fn %Post{} = post, _conn -> String.slice(post.body, 0..5) end]
    ]

  @impl JSONAPIPlug.Resource
  def meta(%Post{} = post, _conn), do: %{slug: to_slug(post.title)}
end

To use the resource module in Phoenix, just call render and pass the data from your controller:

  defmodule MyAppWeb.PostsController do
    ...
    plug JSONAPIPlug.Plug, api: MyApp.API, resource: MyApp.PostResource
    ...

    def create(%Conn{private: %{jsonapi_plug: jsonapi_plug}} = conn, params) do
      post = ...create a post using jsonapi_plug parsed parameters...
      render(conn, "create.json", %{data: post})
    end

    def index(%Conn{private: %{jsonapi_plug: jsonapi_plug}} = conn, _params) do
      posts = ...load data using jsonapi_plug parsed parameters...
      render(conn, "index.json", %{data: posts})
    end

    def show(%Conn{private: %{jsonapi_plug: jsonapi_plug} = conn, _params) do
      post = ...load data using jsonapi_plug parsed parameters...
      render(conn, "show.json", %{data: post})
    end

    def udate(%Conn{private: %{jsonapi_plug: jsonapi_plug}} = conn, params) do
      post = ...update a post using jsonapi_plug parsed parameters...
     render(conn, "update.json", %{data: post})
    end
  end

If you have a Plug application, you can call JSONAPIPlug.Resource.render/5 to generate a JSONAPI.Document with your data for the client. The structure is serializable to JSON with Jason.

See the JSONAPIPlug.Plug and JSONAPIPlug.Resource modules documentation for more information.

contributing

Contributing

  • This project was born as a fork of the jsonapi library but has since been completely rewritten and is now a completely different project.
  • PRs for new features, bug fixes, documentation and tests are welcome
  • If you are proposing a large feature or change, please open an issue for discussion