May 09, 2021 Ember.js Reference documents
In an Ember app, the serializer formats the data that interacts with the background, including the data sent and received. T he JSON API serializes the data by default. If your back end uses a different format, Ember Data allows you to customize the serializer or define a completely different serializer.
Ember Data has three serializers built in. r is the default serializer used with the back-end JSON API. r is a simple serializer that is used to work with a single JSON object or an array of records. RESTSerializer is a complex serializer that supports side loading and was the default serializer before Ember Data 2.0.
When you request data from the server, JSONSerializer considers the data returned by the server to be JSON data that conforms to the following specifications.
Note: Especially if the project is using a custom adapter, the data format returned in the background must comply with the JSOP API specification, otherwise the CRUD operation of the data cannot be implemented, Ember will not be able to parse the data, the knowledge of the custom adapter can be seen in the previous Ember.js Getting Started Guide 44 custom adapter, in the article there is a detailed description of the custom adapter and custom serializer is closely related.
JSONSerializer expects a JSON document that complies with the JSON API specifications and conventions returned in the background. For example, the following JSON data, the format of these data is like this:
For example,
/people/123
response data is as follows:
{
"data": {
"type": "people",
"id": "123",
"attributes": {
"first-name": "Jeff",
"last-name": "Atwood"
}
}
}
If there are multiple datas in the
data
will be returned as an array.
{
"data": [
{
"type": "people",
"id": "123",
"attributes": {
"first-name": "Jeff",
"last-name": "Atwood"
}
},{
"type": "people",
"id": "124",
"attributes": {
"first-name": "chen",
"last-name": "ubuntuvim"
}
}
]
}
Data is sometimes not the subject of a request if the data is linked.
Linked relationships are placed
included
{
"data": {
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"links": {
"self": "http://example.com/articles/1"
},
"relationships": {
"comments": {
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
}
}
}],
"included": [{
"type": "comments",
"id": "5",
"attributes": {
"body": "First!"
},
"links": {
"self": "http://example.com/comments/5"
}
}, {
"type": "comments",
"id": "12",
"attributes": {
"body": "I like XML better"
},
"links": {
"self": "http://example.com/comments/12"
}
}]
}
As you can see from the
id
the comment link with
comment
5
"self": http://example.com/comments/5
T
he comment link with
comment
id
12
"self": http://example.com/comments/12
And these links are placed
included
Ember Data's default serializer is JSON APISerializer, but you can also customize the serializer to override the default serializer.
To customize the serializer, first define an entry
application
the application serializer.
Build directly with commands:
ember g serializer application
// app/serializers/application.js
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
});
You can even define a serializer for a model.
For example, the following code defines a specialized serializer for
post
which is related to how to customize an adapter for a model in the previous custom adapter.
// app/serializers/post.js
import DS from ‘ember-data’;
export default DS.JSONSerializer.extend({
});
If you want to change the JSON data format sent to the back end, you just
serialize
callback and format the data in the callback.
For example, the data format sent by the front end is the following structure,
{
"data": {
"attributes": {
"id": "1",
"name": "My Product",
"amount": 100,
"currency": "SEK"
},
"type": "product"
}
}
But the data structure accepted by the server is the following:
{
"data": {
"attributes": {
"id": "1",
"name": "My Product",
"cost": {
"amount": 100,
"currency": "SEK"
}
},
"type": "product"
}
}
At this point you can
serialize
callback.
// app/serializers/application.js
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
serialize: function(snapshot, options) {
var json = this._super(...arguments); // ??
json.data.attributes.cost = {
amount: json.data.attributes.amount,
currency: json.data.attributes.currency
};
delete json.data.attributes.amount;
delete json.data.attributes.currency;
return json;
}
});
So what if it's the other way around? If the data returned by the backend is in the following format:
{
"data": {
"attributes": {
"id": "1",
"name": "My Product",
"cost": {
"amount": 100,
"currency": "SEK"
}
},
"type": "product"
}
}
However, the format required by the front end is:
{
"data": {
"attributes": {
"id": "1",
"name": "My Product",
"amount": 100,
"currency": "SEK"
},
"type": "product"
}
}
At this point, you can override the callback method
normalizeResponse
normalize
to format the data in the method:
// app/serializers/application.js
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
normalizeResponse: function(store, primaryModelClass, payload, id, requestType) {
payload.data.attributes.amount = payload.data.attributes.cost.amount;
payload.data.attributes.currency = payload.data.attributes.cost.currency;
delete payload.data.attributes.cost;
return this._super(...arguments);
}
});
Each data has a unique value as the
ID
and by default Ember adds a property
id
each model.
If you want to change to a different name, you can specify it in the serializer.
// app/serializers/application.js
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primatyKey: '__id'
});
Change the data primary key name
__id
.
The property names agreed upon by Ember Data are hump-like naming, but the serializer expects a middle-line-separated naming method, although Ember converts automatically and does not require manual designation by the developer. H
owever, if you want to modify this default method, you can simply use the
keyForAttributes
the serializer to specify the separation you prefer.
For example, the following code changes the property name of the serial number to the following dashed separation:
// app/serializers/application.js
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
keyForAttributes: function(attr) {
return Ember.String.underscore(attr);
}
});
If you want to specify an alias for a model property when the model data is serialized and deserated, specify it
attrs
property.
// app/models/person.js
export default DS.Model.extend({
lastName: DS.attr(‘string’)
});
Specify serialized, anti-serialized property alias:
// app/serializers/application.js
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
attrs: {
lastName: ‘lastNameOfPerson’
}
});
Specify the model property
lastNameOfPerson
One model refers
ID
model by ID.
For example, there are two models with a one-to-many relationship:
// app/models/post.js
export default DS.Model.extend({
comments: DS.hasMany(‘comment’, { async: true });
});
The serialized JSON data format is as follows, where the association is implemented through
ID
property values.
{
"data": {
"type": "posts",
"id": "1",
"relationships": {
"comments": {
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
}
}
}
}
As you can see, there are two
comment
associated with
post
post.
In
belongsTo
relationship, the JSON structure is not much different from the hadMany relationship.
hadMany
{
"data": {
"type": "comment",
"id": "1",
"relationships": {
"original-post": {
"data": { "type": "post", "id": "5" },
}
}
}
}
id
an id
comment
1
is associated with a post with an
ID
of
5
post
In some cases, Ember's built-in property types
string
number
boolean
date
are still not sufficient.
For example, when the server returns a non-standard data format.
Ember Data can register the new JSON converter to deform the data and create it directly using
ember g transform coordinate-point
// app/transforms/coordinate-point.js
import DS from 'ember-data';
export default DS.Transform.extend({
deserialize: function(v) {
return [v.get('x'), v.get('y')];
},
serialize: function(v) {
return Ember.create({ x: v[0], y: v[1]});
}
});
Defines a compound property type, which consists of two properties that form a coordinate.
// app/models/curor.js
import DS from 'ember-data';
export default DS.Model.extend({
position: DS.attr(‘coordinate-point’)
});
Custom property types are used in the same way as normal types and are used directly
attr
method.
Finally, when we accept the data returned by the service, the data is shown in the following code:
{
cursor: {
position: [4, 9]
}
}
The model instance is still loaded as a normal object when it is loaded. Y
ou can still
.
The action gets the property value.
var cursor = this.store.findRecord(‘cursor’, 1);
cursor.get(‘position.x’); // => 4
cursor.get(‘position.y’); // => 9
Not all APIs follow the JSON APISerializer convention through data namespaces and copy relationship records. F or example, the system legacy problem, the original API returned only a simple JSON format is not the JSON APISerializer convention format, at this time you can customize the serializer to adapt to the old interface. And it can also be compatible with the use of RESTAdapter to serial number these simple JSON data.
// app/serializer/application.js
export default DS.JSONSerializer.extend({
// ...
});
Although Ember Data encourages you to copy model associations, sometimes when working with legacy APIs, you will find that other model associations are embedded in the JSON that you need to work with.
But
EmbeddedRecordsMixin
you solve this problem.
For
post
contains an
author
record.
{
"id": "1",
"title": "Rails is omakase",
"tag": "rails",
"authors": [
{
"id": "2",
"name": "Steve"
}
]
}
The model associations you can define in are as follows:
// app/serializers/post.js
export default DS.JSONSerialier.extend(DS.EmbeddedRecordsMixin, {
attrs: {
author: {
serialize: ‘records’,
deserialize: ‘records’
}
}
});
If you occur the relationship between the object itself needs to be serialized and deserated embedding, you can use the
embedded
// app/serializers/post.js
export default DS.JSONSerialier.extend(DS.EmbeddedRecordsMixin, {
attrs: {
author: { embedded: ‘always’ }
}
});
The serialization and anti-serialization settings have three keywords:
records
used to mark that all records are serialized and reserated
ids
used to mark ids that are only serialized and deserated records
false
used to mark records that do not need to be serialized and reserated
For example, you might find that you want to read an embedded record extract when a JSON payload only includes the identity of the relationship in the serialized record. T
his may
serialize: ids
You can also choose to serialize the relationship
serialize: false
export default DS.JSONSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
author: {
serialize: false,
deserialize: 'records'
},
comments: {
deserialize: 'records',
serialize: 'ids'
}
}
});
If you don't
attrs
to specify the association of the model,
EmbeddedRecordsMixin
will have the following default behavior:
belongsTo:{serialize: ‘id’, deserialize: ‘id’ }
hasMany: { serialize: false, deserialize: ‘ids’ }
If your project requires a custom serializer, Ember recommends extending JSONAIPSerializer or JSONSerializer to fulfill your needs. H
owever, if you want to completely create a brand new serializer that is different from JSONAIPSerizer and JSONSerializer you can extend
DS.Serializer
class, but you have to implement three methods:
Knowing normalized JSON data is important for Ember Data, and these property values will not be automatically updated if the model property names do not conform to the Ember Data specification. I
f the returned data is not specified in the model, the data is ignored.
For example, as defined
this.store.push()
method accepts the format shown in the second piece of code.
// app/models/post.js
import DS from 'ember-data';
export default DS.Model.extend({
title: DS.attr(‘string’),
tag: DS.attr(‘string’),
comments: hasMany(‘comment’, { async: true }),
relatedPosts: hasMany(‘post’)
});
{
data: {
id: "1",
type: 'post',
attributes: {
title: "Rails is omakase",
tag: "rails",
},
relationships: {
comments: {
data: [{ id: "1", type: 'comment' },
{ id: "2", type: 'comment' }],
},
relatedPosts: {
data: {
related: "/api/v1/posts/1/related-posts/"
}
}
}
}
Each serialized record must be converted correctly to an Ember Data record in this format.
The content of this article is very difficult, belongs to the content of the advanced topic! I
f it doesn't matter if you don't understand for a time, you can build your project using
firebase,
and then look back at this
and the 44 custom adapters in the last Ember.js Getting Started Guide,
so you don't have to understand! !
By the end of this article, the basics of Ember have been fully covered!!! F
rom 2015-08-26 to now just 2 months, the original plan was completed in 3 months, a month ahead of schedule, the reason is that the content behind the difficult, understanding bias! T
he quality of the article is also not good, feel the time is relatively hasty, said to save a lot of time! (
This article is rearranged and published, the original version of the blog post was released when Ember or
version 2.0, is now 2.5!!
/b10>)
Introduction to the intention to introduce APPLICATION CONCERNS and TESTING these two chapters! I
t is also possible to change the old Ember todomvc case to Ember 2.0, which is just the right way to practice !!!
Thankfully, the goal: to change the old Ember todomvc case to Ember 2.0, and !!! A
nd extended a lot of features about the
code situation todos v2,
welcome readers to fork to learn! G
ive me a star if you think
star
useful! !
Thank you!!!
The full code of the blog post
is placed in Github
(the blog post has been modified several times, and the code on the blog post may be different from the github code, but the impact is small!). I
f you think the blog post is a bit useful to you, please give me a star on the
star
project.
Yours is definitely the biggest motivation for me!!