Customizing Serializers

In Ember Data, serializers format the data sent to and received from
the backend store. By default, Ember Data serializes data using the
JSON API format. If your backend uses a different
format, Ember Data allows you to customize the serializer or use a
different serializer entirely.

Ember Data ships with 3 serializers. The
JSONAPISerializer
is the default serializer and works with JSON API backends. The
JSONSerializer
is a simple serializer for working with single json object or arrays of records. The
RESTSerializer
is a more complex serializer that supports sideloading and was the default
serializer before 2.0.

JSONAPISerializer Conventions

When requesting a record, the JSONAPISerializer expects your server
to return a JSON representation of the record that conforms to the
following conventions.

JSON API Document

The JSONAPISerializer expects the backend to return a JSON API
Document that follows the JSON API specification and the conventions
of the examples found on http://jsonapi.org/format. This means all
type names should be pluralized and attribute and relationship names
should be dash-cased. For example, if you request a record from
/people/123, the response should look like this:

Sideloaded Data

Data that is not a part of the primary request but includes linked
relationships should be placed in an array under the included
key. For example, if you request /articles/1 and the backend also
returned any comments associated with that person the response
should look like this:

Customizing Serializers

Ember Data uses the JSONAPISerializer by default, but you can
override this default by defining a custom serializer. There are two
ways to define a custom serializer. First, you can define a custom
serializer for your entire application by defining an "application"
serializer.

IDs

In order to keep track of unique records in the store Ember Data
expects every record to have an id property in the payload. Ids
should be unique for every unique record of a specific type. If your
backend uses a key other than id you can use the
serializer's primaryKey property to correctly transform the id
property to id when serializing and deserializing data.

If the attributes returned by your server use a different convention
you can use the serializer's
keyForAttribute()
method to convert an attribute name in your model to a key in your JSON
payload. For example, if your backend returned attributes that are
under_scored instead of dash-cased you could override the keyForAttribute
method like this.

Irregular keys can be mapped with a custom serializer. The attrs
object can be used to declare a simple mapping between property names
on DS.Model records and payload keys in the serialized JSON object
representing the record. An object with the property key can also be
used to designate the attribute's key on the response payload.

If the JSON for person has a key of lastNameOfPerson, and the
desired attribute name is simply lastName, then create a custom
Serializer for the model and override the attrs property.

If position is modified and saved, it will pass through the
serialize function in the transform and again be presented as
an array in JSON.

JSONSerializer

Not all APIs follow the conventions that the JSONAPISerializer uses
with a data namespace and sideloaded relationship records. Some
legacy APIs may return a simple JSON payload that is just the requested
resource or an array of serialized records. The JSONSerializer is a
serializer that ships with Ember Data that can be used alongside the
RESTAdapter to serialize these simpler APIs.

To use it in your application you will need to define a
serializer:application that extends the JSONSerializer.

For requests that are only expected to return 0 or more records
(e.g. store.findAll('post') or store.query('post', { filter: { status: 'draft' } }))
the JSONSerializer expects the response to be a JSON array that
looks similar to this:

The JSONAPISerializer is built on top of the JSONSerializer so they share
many of the same hooks for customizing the behavior of the
serialization process. Be sure to check out the
API docs
for a full list of methods and properties.

EmbeddedRecordMixin

Although Ember Data encourages you to sideload your relationships,
sometimes when working with legacy APIs you may discover you need to
deal with JSON that contains relationships embedded inside other
records. The EmbeddedRecordsMixin is meant to help with this problem.

To set up embedded records, include the mixin when extending a
serializer then define and configure embedded relationships.

For example, if your post model contained an embedded author record
that looks similar to this:

If you find yourself needing to both serialize and deserialize the
embedded relationship you can use the shorthand option of { embedded:
'always' }. The example above could therefore be expressed as such:

For example you may find that you want to read an embedded record when
extracting a JSON payload but only include the relationship's id when
serializing the record. This is possible by using the serialize:
'ids' option. You can also opt out of serializing a relationship by
setting serialize: false.

There is an option of not embedding JSON in the serialized payload by
using serialize: 'ids'. If you do not want the relationship sent at
all, you can use serialize: false.

Authoring Serializers

If you would like to create a custom serializer its recommend that you
start with the JSONAPISerializer or JSONSerializer and extend one of
those to match your needs.
However, if your payload is extremely different from one of these
serializers you can create your own by extending the DS.Serializer
base class.

A serializer in Ember Data is responsible for normalizing a payload
from an adapter into the format that Ember Data understands.
It is also responsible for transforming a snapshot of a record into
the payload that an adapter will send to the backend.

A serializer has two main roles in Ember Data.
First, it is responsible for taking a response from an adapter and
serializing it into the normalized JSON format that Ember Data
understands.
Secondly, it transforms snapshots of records into a payload the
adapter will send to the server when creating, updating, or deleting a
record.

Ember Data's Normalized JSON Format

The normalized JSON format that Ember Data expects is a
JSON API document with a couple of additional
restrictions.

First, it is important to make sure that the type name of a record
in the normalized JSON object exactly matches the filename of the
model defined for this record type.
By convention Model names are singular in Ember Data, however, the
example type names shown in the
JSON API spec are pluralized.
The JSON API spec itself is agnostic about inflection rules, however,
Ember Data's own JSONAPISerializer assumes types are plural and it
will automatically singularize the types.

Second, attribute and relationship names in the JSON API document
should exactly match the name and casing of the DS.attr(),
DS.belongsTo() and DS.hasMany(), properties defined on the
Model.

By convention these property names are camelCase in Ember Data models.
As with the type names, this is different from the example attribute
and relationship names shown in the
JSON API spec.
The examples in the spec use dash-case for attribute and relationship
names. However, the spec does not require attribute or relationship
names to follow any specific casing convention.
If you are using Ember Data's own JSONAPISerializer it will assume
the attribute and relationship names from your API are dash-case and
automatically transform them to camelCase when it creates the
normalized JSON object.

Other than these two restrictions, Ember Data's normalized JSON object
follows the JSON API specification.

Note that the type is "post" to match the post model and the
relatedPosts relationship in the document matches the
relatedPosts: hasMany('post') on the model.

Normalizing adapter responses

When creating a custom serializer you will need to define a
normalizeResponse
method to transform the response from the adapter into the normalized
JSON object described above.

This method receives the store, the Model class for the request, the
payload, the id of the record request (or null if there is
no id associated with the request), and the request type (a string with
the possible values of: 'findRecord', 'queryRecord', 'findAll',
'findBelongsTo', 'findHasMany', 'findMany', 'query',
'createRecord', 'deleteRecord', and 'updateRecord') as arguments.

A custom serializer will also need to define a
normalize
method.
This method is called by store.normalize(type, payload) and is often
used for normalizing requests made outside of Ember Data because they
do not fall into the normal CRUD flow that the adapter provides.

Serializing records

Finally a serializer will need to implement a
serialize
method.
Ember Data will provide a record snapshot and an options hash and this
method should return an object that the adapter will send to the
server when creating, updating or deleting a record.

Community Serializers

If none of the built-in Ember Data Serializers work for your backend,
be sure to check out some of the community maintained Ember Data
Adapters and Serializers.
A good place to search for them is
Ember Observer.