JaSerializer.Serializer

Define a serialization schema.

Provides serialize/2, has_many/2, has_one/2, attributes1 and location1 macros to define how your model (struct or map) will be rendered in the JSONAPI.org 1.0 format.

Defines format/1, format/2 and format/3 used to convert models (and list of models) for encoding in your JSON library of choice.

Example

defmodule PostSerializer do
  use JaSerializer

  serialize "posts" do
    location "/posts/:id"
    attributes [:title, :body, :excerpt, :tags]
    has_many :comments,
      link: "/posts/:id/comments",
    has_one :author,
      include: PersonSerializer
  end

  def excerpt(post, _conn) do
    [first | _ ] = String.split(post.body, ".")
    first
  end
end

post = %Post{
  id: 1,
  title: "jsonapi.org + Elixir = Awesome APIs",
  body: "so. much. awesome.",
  author: %Person{name: "Alan"}
}

post
|> PostSerializer.format
|> Poison.encode!
Source

Summary

attributes(atts)

Defines a list of attributes to be included in the payload

has_many(name, opts \\ [])

Add a has_many relationship to be serialized

has_one(name, opts \\ [])

See documentation for has_many/2

location(uri)

Defines the canoical path for retrieving this resource

serialize(type, list2)

Define a serialization schema

Macros

attributes(atts)

Defines a list of attributes to be included in the payload.

An overrideable function for each attribute is generated with the same name as the attribute. The function’s default behavior is to retrieve a field with the same name from the model.

For example, if you have attributes [:body] a function body/2 is defined on the serializer with a default behavior of Map.get(model, :body).

Source
has_many(name, opts \\ [])

Add a has_many relationship to be serialized.

Relationships may be included in any of three composeable ways:

  • Links
  • Resource Identifiers
  • Includes

Relationship Source

When you define a relationship, a function is defined of the same name in the serializer module. This function is overrideable but by default attempts to access a field of the same name as the relationship on the map/struct passed in. The field may be changed using the field option.

For example if you have_many :comments a function comments2 is defined which calls Dict.get(model, :comments) by default.

Link based relationships

Specify a uri which responds with the related resources. See location/1 for defining uris.

The relationship source is disregarded when linking.

defmodule PostSerializer do
  use JaSerializer

  serialize "posts" do
    has_many :comments, link: "/posts/:id/comments"
  end
end

Resource Identifier Relationships

Adds a list of id and type pairs to the response with the assumption the API consumer can use them to retrieve the related resources as needed.

The relationship source should return either a list of ids or maps/structs that have an id field.

defmodule PostSerializer do
  use JaSerializer

  serialize "posts" do
    has_many :comments, type: "comments"
  end

  def comments(post, _conn) do
    post |> PostModel.get_comments |> Enum.map(&(&1.id))
  end
end

Included Relationships

Adds a list of id and type pairs, just like Resource Indentifier relationships, but also adds the full serialized resource to the response to be “sideloaded” as well.

The relationship source should return a list of maps/structs.

WARNING: Currently sideloaded resources do not have thier own included resources included.

defmodule PostSerializer do
  use JaSerializer

  serialize "posts" do
    has_many :comments, include: CommentSerializer
  end

  def comments(post, _conn) do
    post |> PostModel.get_comments
  end
end

defmodule CommentSerializer do
  use JaSerializer

  serialize "comments" do
    has_one :post, field: :post_id, type: "posts"
    attributes [:body]
  end
end
Source
has_one(name, opts \\ [])

See documentation for has_many/2.

API is the exact same.

Source
location(uri)

Defines the canoical path for retrieving this resource.

String Examples

String may be either a full url or a relative path. Path segments begining with a colin are called as functions on the serializer with the model and conn passed in.

defmodule PostSerializer do
  use JaSerializer

  serialize "posts" do
    location "/posts/:id"
  end
end

defmodule CommentSerializer do
  use JaSerializer

  serialize "comment" do
    location "http://api.example.com/posts/:post_id/comments/:id"
  end

  def post_id(comment, _conn), do: comment.post_id
end

Atom Example

When an atom is passed in it is assumed it is a function that will return a relative or absolute path.

defmodule PostSerializer do
  use JaSerializer
  import MyPhoenixApp.Router.Helpers

  serialize "post" do
    location :post_url
  end

  def post_url(post, conn) do
    #TODO: Verify conn can be used here instead of Endpoint
    post_path(conn, :show, post.id)
  end
end
Source
serialize(type, list2)

Define a serialization schema.

The type should be the plural version of the type of object being serialized. This maps to the JSONAPI type field.

Defines an overridable id function that is expected to return the id of the object being serialized. Defaults to Map.get(model, :id).

Example

defmodule PostSerializer do
  use JaSerializer

  serialize "posts" do
    # JaSerializer.Serialization macros available here.
  end

  # Optional override
  def id(post, conn) do
    post.id
  end
end
Source