ja_serializer v0.18.1 JaSerializer.Serializer behaviour View Source
A Behaviour for defining JSON-API.org spec complaint payloads.
The following callbacks are available:
id/2
- Return ID of struct to be serialized.type/2
- Return string type of struct to be serialized.attributes/2
- A map of attributes to be serialized.relationships/2
- A map ofHasMany
andHasOne
data structures.links/2
- A keyword list of any links pertaining to this struct.meta/2
- A map of any additional meta information to be serialized.preload/3
- A special callback that can be used to preload related data.
A Serializer (or view) is typically one of the few places in an API where content and context are both present. To accommodate this each callback gets the data being serialized (typically a struct, often called a model) and the Plug.Conn as arguments. Context data such as the current user, role, etc should typically be made available on the conn.
When use
ing this module all callbacks get a default, overridable
implementation. The JaSerializer.DSL
module also provides some default
implementations of these callbacks built up from the DSL. When using the DSL
overriding the Behaviour functions can be a great way to customize
conditional logic.
While not typically used directly, the interface for returning formatted data is also defined. The results still need to be encoded into JSON as appropriate.
defmodule FooSerializer do
use JaSerializer
end
# Format one foo
FooSerializer.format(one_foo, conn, meta)
# Format many foos
FooSerializer.format(many_foos, conn, meta)
Link to this section Summary
Callbacks
Returns a map of attributes to be serialized.
The id to be used in the resource object.
return links about this resource
Adds meta data to the individual resource being serialized.
A special callback that can be used to preload related data.
A callback that should return a map of relationship structs.
The type to be used in the resource object.
Link to this section Types
Link to this section Callbacks
Specs
attributes(map(), Plug.Conn.t()) :: map()
Returns a map of attributes to be serialized.
The default implementation returns all the data's fields except id
, type
,
and __struct__
.
A typical non-DSL implementation looks like:
defmodule UserSerializer do
def attributes(user, conn) do
Map.take(user, [:email, :name])
end
end
UserSerializer.attributes(user, conn)
# %{email: "...", name: "..."}
If using the JaSerializer.DSL
the default implementation is based on the
JaSerializer.DSL.attributes/1
macro. Eg:
defmodule UserSerializer do
attributes [:email, :name, :is_admin]
end
UserSerializer.attributes(user, conn)
# %{email: "...", name: "...", is_admin: "..."}
Overriding this callback can be a good way to customize attribute behaviour based on the context (conn) with super.
defmodule UserSerializer do
attributes [:email, :name, :is_admin]
def attributes(user, %{assigns: %{current_user: %{is_admin: true}}}) do
super(user, conn)
end
def attributes(user, conn) do
super(user, conn)
|> Map.take([:email, :name])
end
end
UserSerializer.attributes(user, conn)
# %{email: "...", name: "..."}
Specs
id(data(), Plug.Conn.t()) :: id()
The id to be used in the resource object.
http://jsonapi.org/format/#document-resource-objects
Default implementation attempts to get the :id field from the struct.
To override simply define the id function:
def id(struct, _conn), do: struct.slug
Specs
links(map(), Plug.Conn.t()) :: map()
return links about this resource
Specs
meta(map(), Plug.Conn.t()) :: map() | nil
Adds meta data to the individual resource being serialized.
NOTE: To add meta data to the top level object pass the meta:
option into
YourSerializer.format/3.
A nil return value results in no meta key being added to the serializer. A map return value will be formatted with JaSerializer.Formatter.format/1.
The default implementation returns nil.
Specs
A special callback that can be used to preload related data.
Unlike the other callbacks, this callback is ONLY executed on the top level data being serialized. Also unlike any other callback when serializing a list of data (eg: from an index action) it receives the entire list, not each individual post. When serializing a single record (eg, show, create, update) a single record is received.
The primary use case of the callback is to preload all the relationships you need. For example:
@default_includes [:category, comments: :author]
def preload(record_or_records, _conn, []) do
MyApp.Repo.preload(record_or_records, @default_includes)
end
def preload(record_or_records, _conn, include_opts) do
MyApp.Repo.preload(record_or_records, include_opts)
end
Specs
relationships(map(), Plug.Conn.t()) :: map()
A callback that should return a map of relationship structs.
Example:
def relationships(article, _conn) do
%{
comments: %HasMany{
serializer: MyApp.CommentView,
include: true,
data: article.comments,
},
author: %HasOne{
serializer: MyApp.AuthorView,
include: true,
data: article.author,
}
}
end
See JaSerializer.Relationship.HasMany for details on fields.
When using the DSL this is defined for you based on the has_many and has_one macros.
Specs
type() :: String.t()
The type to be used in the resource object.
http://jsonapi.org/format/#document-resource-objects
Default implementation attempts to infer the type from the serializer module's name. For example:
MyApp.UserView becomes "user"
MyApp.V1.Serializers.Post becomes "post"
MyApp.V1.CommentsSerializer becomes "comments"
To override simply define the type function:
def type(_post,_conn), do: "category"
Or
def type, do: "category"
Specs
type(map(), Plug.Conn.t()) :: String.t()