JSONAPI Cheatsheet

Quick reference for the most common JSONAPI functions, view callbacks, and configuration.

Setup

# mix.exs
{:jsonapi, "~> 1.10.0"}

# config/config.exs
config :jsonapi,
  namespace: "/api",
  field_transformation: :underscore,
  json_library: Jason,
  remove_links: false,
  paginator: nil

Defining a View

defmodule MyApp.PostView do
  use JSONAPI.View, type: "posts"

  def fields, do: [:title, :body, :inserted_at]

  def relationships do
    [
      author: {MyApp.UserView, :include},
      comments: MyApp.CommentView
    ]
  end
end

View Callbacks

CallbackSignaturePurpose
fields/0() -> [atom]Fields to serialize
relationships/0() -> keywordRelationship definitions
meta/2(data, conn) -> mapPer-resource metadata
links/2(data, conn) -> mapCustom link objects
hidden/1(data) -> [atom]Fields to exclude
id/1(data) -> String.tCustom ID extraction
namespace/0() -> String.tURL path prefix
url_for/2(data, conn) -> String.tCustom resource URL

Computed Fields

def fields, do: [:title, :excerpt]

def excerpt(post, _conn) do
  String.slice(post.body, 0..100)
end

Relationships

# Basic — link only
[comments: MyApp.CommentView]

# Always include when loaded
[author: {MyApp.UserView, :include}]

# Rename (internal_field: {:api_name, View, :include})
[creator: {:author, MyApp.UserView, :include}]

Rendering

# Phoenix controller
render(conn, MyApp.PostView, "show.json", %{data: post})
render(conn, MyApp.PostView, "index.json", %{data: posts})

# With metadata
render(conn, MyApp.PostView, "index.json", %{
  data: posts,
  meta: %{total: 42}
})

# Standalone
JSONAPI.Serializer.serialize(MyApp.PostView, data, conn)
JSONAPI.Serializer.serialize(MyApp.PostView, data, conn, meta)

Phoenix Pipeline Plugs

pipeline :api do
  plug :accepts, ["json"]
  plug JSONAPI.EnsureSpec
  plug JSONAPI.Deserializer
  plug JSONAPI.UnderscoreParameters
end
PlugPurpose
JSONAPI.EnsureSpecValidate content types and request structure
JSONAPI.DeserializerFlatten JSON:API body into params map
JSONAPI.UnderscoreParametersConvert param keys to underscore
JSONAPI.ContentTypeNegotiationCheck Content-Type and Accept headers
JSONAPI.FormatRequiredVerify request body format
JSONAPI.IdRequiredConfirm ID matches URI
JSONAPI.ResponseContentTypeSet response content type

Query Parser

plug JSONAPI.QueryParser,
  filter: ~w(name email),
  sort: ~w(name inserted_at),
  view: MyApp.UserView

Parsed Output (conn.assigns.jsonapi_query)

# GET /api/users?sort=-name&filter[email]=jane@example.com&include=posts

%JSONAPI.Config{
  sort: [desc: :name],
  filter: %{"email" => "jane@example.com"},
  include: [:posts],
  page: %{},
  fields: %{}
}

Query Parameter Formats

ParameterExampleParsed
Sort ascending?sort=name[asc: :name]
Sort descending?sort=-name[desc: :name]
Filter?filter[name]=Jane%{"name" => "Jane"}
Include?include=author,comments[:author, :comments]
Sparse fields?fields[posts]=title,body%{"posts" => [:title, :body]}
Pagination?page[number]=2&page[size]=10%{"number" => "2", "size" => "10"}

Pagination

# Global config
config :jsonapi, paginator: MyApp.PagePaginator

# Per-view
use JSONAPI.View, type: "posts", paginator: MyApp.PagePaginator

# Paginator behaviour
defmodule MyApp.PagePaginator do
  @behaviour JSONAPI.Paginator

  @impl true
  def paginate(data, view, conn, page, options) do
    %{first: "...", last: "...", next: "...", prev: nil}
  end
end

Field Transformation

config :jsonapi, field_transformation: :camelize
Option:inserted_at becomes
:underscore"inserted_at"
:camelize"insertedAt"
:dasherize"inserted-at"

Polymorphic Resources

use JSONAPI.View, polymorphic_resource?: true

def polymorphic_type(%Image{}), do: "images"
def polymorphic_type(%Video{}), do: "videos"

def polymorphic_fields(%Image{}), do: [:url, :alt_text]
def polymorphic_fields(%Video{}), do: [:url, :duration]

Configuration Reference

OptionDefaultDescription
namespacenilURL path prefix
field_transformation:underscoreField name format
json_libraryJasonJSON encoder
hostfrom connOverride host
schemefrom connOverride scheme
remove_linksfalseStrip link objects
paginatornilDefault paginator module