View Source JSONAPI.View behaviour (jsonapi v1.8.3)
A View is simply a module that defines certain callbacks to configure proper rendering of your JSONAPI documents.
defmodule PostView do
use JSONAPI.View
def fields, do: [:id, :text, :body]
def type, do: "post"
def relationships do
[author: UserView,
comments: CommentView]
end
end
defmodule UserView do
use JSONAPI.View
def fields, do: [:id, :username]
def type, do: "user"
def relationships, do: []
end
defmodule CommentView do
use JSONAPI.View
def fields, do: [:id, :text]
def type, do: "comment"
def relationships do
[user: {UserView, :include}]
end
end
defmodule DogView do
use JSONAPI.View, namespace: "/pupperz-api"
end
You can now call UserView.show(user, conn, conn.params)
and it will render
a valid jsonapi doc.
Fields
By default, the resulting JSON document consists of fields, defined in the fields/0
function. You can define custom fields or override current fields by defining a
2-arity function inside the view that takes data
and conn
as arguments and has
the same name as the field it will be producing. Refer to our fullname/2
example below.
defmodule UserView do
use JSONAPI.View
def fullname(data, conn), do: "fullname"
def fields, do: [:id, :username, :fullname]
def type, do: "user"
def relationships, do: []
end
Fields may be omitted manually using the hidden/1
function.
defmodule UserView do
use JSONAPI.View
def fields, do: [:id, :username, :email]
def type, do: "user"
def hidden(_data) do
[:email] # will be removed from the response
end
end
In order to use sparse fieldsets
you must include the JSONAPI.QueryParser
plug.
If you want to fetch fields from the given data dynamically, you can use the
get_field/3
callback.
defmodule UserView do
use JSONAPI.View
def fields, do: [:id, :username, :email]
def type, do: "user"
def get_field(field, data, _conn) do
Map.fetch!(data, field)
end
end
Relationships
Currently the relationships callback expects that a map is returned configuring the information you will need. If you have the following Ecto Model setup
defmodule User do
schema "users" do
field :username
has_many :posts
has_one :image
end
end
and the includes setup from above. If your Post has loaded the author and the query asks for it then it will be loaded.
So for example:
GET /posts?include=post.author
if the author record is loaded on the Post, and you are using
the JSONAPI.QueryParser
it will be included in the includes
section of the JSONAPI document.
If you always want to include a relationship. First make sure its always preloaded
and then use the [user: {UserView, :include}]
syntax in your includes
function. This tells
the serializer to always include if its loaded.
Options
:host
(binary) - Allows thehost
to be overridden for generated URLs. Defaults tohost
of the suppliedconn
.:scheme
(atom) - Enables configuration of the HTTP scheme for generated URLS. Defaults toscheme
from the providedconn
.:namespace
(binary) - Allows the namespace of a given resource. This may be configured globally or overridden on the View itself. Note that if you have a globally defined namespace and need to remove the namespace for a resource, set the namespace to a blank String.
The default behaviour for host
and scheme
is to derive it from the conn
provided, while the
default style for presentation in names is to be underscored and not dashed.
Summary
Types
Callbacks
@callback attributes(data(), Plug.Conn.t() | nil) :: map()
@callback fields() :: [field()]
@callback get_field(field(), data(), Plug.Conn.t()) :: any()
@callback id(data()) :: resource_id() | nil
@callback links(data(), Plug.Conn.t()) :: links()
@callback meta(data(), Plug.Conn.t()) :: meta() | nil
@callback namespace() :: String.t()
@callback pagination_links( data(), Plug.Conn.t(), JSONAPI.Paginator.page(), JSONAPI.Paginator.options() ) :: JSONAPI.Paginator.links()
@callback path() :: String.t() | nil
@callback type() :: resource_type()
@callback url_for(data(), Plug.Conn.t() | nil) :: String.t()
@callback url_for_pagination(data(), Plug.Conn.t(), JSONAPI.Paginator.params()) :: String.t()
@callback url_for_rel(term(), String.t(), Plug.Conn.t() | nil) :: String.t()
@callback visible_fields(data(), Plug.Conn.t() | nil) :: [atom()]
Functions
@spec url_for(t(), term(), Plug.Conn.t() | nil) :: String.t()
@spec url_for_rel(t(), data(), resource_type(), Plug.Conn.t() | nil) :: String.t()
@spec url_for_rel(t(), data(), Plug.Conn.query_params(), JSONAPI.Paginator.params()) :: String.t()
@spec visible_fields(t(), data(), Plug.Conn.t() | nil) :: [atom()]