@ember-data/serializer 4.10.0-alpha.2 → 4.10.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/-private.js +210 -0
- package/addon/-private.js.map +1 -0
- package/addon/{-private/embedded-records-mixin.js → embedded-records-mixin-0a9e9148.js} +87 -146
- package/addon/embedded-records-mixin-0a9e9148.js.map +1 -0
- package/addon/index.js +178 -0
- package/addon/index.js.map +1 -0
- package/addon/json-api.js +96 -233
- package/addon/json-api.js.map +1 -0
- package/addon/json.js +198 -432
- package/addon/json.js.map +1 -0
- package/addon/rest.js +133 -270
- package/addon/rest.js.map +1 -0
- package/addon/{-private/transforms/transform.js → transform-63fba437.js} +9 -15
- package/addon/transform-63fba437.js.map +1 -0
- package/addon/transform.js +3 -4
- package/addon/transform.js.map +1 -0
- package/addon-main.js +90 -0
- package/package.json +39 -8
- package/addon/-private/index.js +0 -11
- package/addon/-private/transforms/boolean.js +0 -70
- package/addon/-private/transforms/date.js +0 -59
- package/addon/-private/transforms/number.js +0 -57
- package/addon/-private/transforms/string.js +0 -38
- package/addon/index.ts +0 -259
- package/blueprints/serializer/files/__root__/__path__/__name__.js +0 -4
- package/blueprints/serializer/index.js +0 -14
- package/blueprints/serializer/native-files/__root__/__path__/__name__.js +0 -4
- package/blueprints/serializer-test/index.js +0 -29
- package/blueprints/serializer-test/mocha-files/__root__/__path__/__test__.js +0 -20
- package/blueprints/serializer-test/mocha-rfc-232-files/__root__/__path__/__test__.js +0 -25
- package/blueprints/serializer-test/qunit-files/__root__/__path__/__test__.js +0 -24
- package/blueprints/transform/files/__root__/__path__/__name__.js +0 -11
- package/blueprints/transform/index.js +0 -7
- package/blueprints/transform/native-files/__root__/__path__/__name__.js +0 -11
- package/blueprints/transform-test/index.js +0 -29
- package/blueprints/transform-test/mocha-files/__root__/__path__/__test__.js +0 -17
- package/blueprints/transform-test/mocha-rfc-232-files/__root__/__path__/__test__.js +0 -14
- package/blueprints/transform-test/qunit-files/__root__/__path__/__test__.js +0 -13
- package/index.js +0 -25
package/addon/json-api.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
* @module @ember-data/serializer/json-api
|
|
3
|
-
*/
|
|
1
|
+
import { macroCondition, isDevelopingApp } from '@embroider/macros';
|
|
4
2
|
import { assert, warn } from '@ember/debug';
|
|
5
3
|
import { dasherize } from '@ember/string';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import { pluralize, singularize } from 'ember-inflector';
|
|
10
|
-
|
|
11
|
-
import JSONSerializer from '@ember-data/serializer/json';
|
|
4
|
+
import { typeOf, isNone } from '@ember/utils';
|
|
5
|
+
import { singularize, pluralize } from 'ember-inflector';
|
|
6
|
+
import JSONSerializer from "./json";
|
|
12
7
|
|
|
13
8
|
/**
|
|
14
9
|
Ember Data 2.0 Serializer:
|
|
@@ -141,15 +136,12 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
141
136
|
documentHash.data = this._normalizeResourceHelper(documentHash.data);
|
|
142
137
|
} else if (Array.isArray(documentHash.data)) {
|
|
143
138
|
let ret = new Array(documentHash.data.length);
|
|
144
|
-
|
|
145
139
|
for (let i = 0; i < documentHash.data.length; i++) {
|
|
146
140
|
let data = documentHash.data[i];
|
|
147
141
|
ret[i] = this._normalizeResourceHelper(data);
|
|
148
142
|
}
|
|
149
|
-
|
|
150
143
|
documentHash.data = ret;
|
|
151
144
|
}
|
|
152
|
-
|
|
153
145
|
if (Array.isArray(documentHash.included)) {
|
|
154
146
|
let ret = new Array();
|
|
155
147
|
for (let i = 0; i < documentHash.included.length; i++) {
|
|
@@ -160,13 +152,10 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
160
152
|
ret.push(normalized);
|
|
161
153
|
}
|
|
162
154
|
}
|
|
163
|
-
|
|
164
155
|
documentHash.included = ret;
|
|
165
156
|
}
|
|
166
|
-
|
|
167
157
|
return documentHash;
|
|
168
158
|
},
|
|
169
|
-
|
|
170
159
|
/**
|
|
171
160
|
@method _normalizeRelationshipDataHelper
|
|
172
161
|
@param {Object} relationshipDataHash
|
|
@@ -175,10 +164,8 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
175
164
|
*/
|
|
176
165
|
_normalizeRelationshipDataHelper(relationshipDataHash) {
|
|
177
166
|
relationshipDataHash.type = this.modelNameFromPayloadKey(relationshipDataHash.type);
|
|
178
|
-
|
|
179
167
|
return relationshipDataHash;
|
|
180
168
|
},
|
|
181
|
-
|
|
182
169
|
/**
|
|
183
170
|
@method _normalizeResourceHelper
|
|
184
171
|
@param {Object} resourceHash
|
|
@@ -187,29 +174,25 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
187
174
|
*/
|
|
188
175
|
_normalizeResourceHelper(resourceHash) {
|
|
189
176
|
assert(this.warnMessageForUndefinedType(), !isNone(resourceHash.type));
|
|
190
|
-
|
|
191
177
|
let modelName, usedLookup;
|
|
192
|
-
|
|
193
178
|
modelName = this.modelNameFromPayloadKey(resourceHash.type);
|
|
194
179
|
usedLookup = 'modelNameFromPayloadKey';
|
|
195
|
-
|
|
196
180
|
if (!this.store.getSchemaDefinitionService().doesTypeExist(modelName)) {
|
|
197
181
|
warn(this.warnMessageNoModelForType(modelName, resourceHash.type, usedLookup), false, {
|
|
198
|
-
id: 'ds.serializer.model-for-type-missing'
|
|
182
|
+
id: 'ds.serializer.model-for-type-missing'
|
|
199
183
|
});
|
|
200
184
|
return null;
|
|
201
185
|
}
|
|
202
|
-
|
|
203
186
|
let modelClass = this.store.modelFor(modelName);
|
|
204
187
|
let serializer = this.store.serializerFor(modelName);
|
|
205
|
-
let {
|
|
188
|
+
let {
|
|
189
|
+
data
|
|
190
|
+
} = serializer.normalize(modelClass, resourceHash);
|
|
206
191
|
return data;
|
|
207
192
|
},
|
|
208
|
-
|
|
209
193
|
/**
|
|
210
194
|
Normalize some data and push it into the store.
|
|
211
|
-
|
|
212
|
-
@method pushPayload
|
|
195
|
+
@method pushPayload
|
|
213
196
|
@public
|
|
214
197
|
@param {Store} store
|
|
215
198
|
@param {Object} payload
|
|
@@ -218,7 +201,6 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
218
201
|
let normalizedPayload = this._normalizeDocumentHelper(payload);
|
|
219
202
|
store.push(normalizedPayload);
|
|
220
203
|
},
|
|
221
|
-
|
|
222
204
|
/**
|
|
223
205
|
@method _normalizeResponse
|
|
224
206
|
@param {Store} store
|
|
@@ -234,47 +216,32 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
234
216
|
let normalizedPayload = this._normalizeDocumentHelper(payload);
|
|
235
217
|
return normalizedPayload;
|
|
236
218
|
},
|
|
237
|
-
|
|
238
219
|
normalizeQueryRecordResponse() {
|
|
239
220
|
let normalized = this._super(...arguments);
|
|
240
|
-
|
|
241
|
-
assert(
|
|
242
|
-
'Expected the primary data returned by the serializer for a `queryRecord` response to be a single object but instead it was an array.',
|
|
243
|
-
!Array.isArray(normalized.data)
|
|
244
|
-
);
|
|
245
|
-
|
|
221
|
+
assert('Expected the primary data returned by the serializer for a `queryRecord` response to be a single object but instead it was an array.', !Array.isArray(normalized.data));
|
|
246
222
|
return normalized;
|
|
247
223
|
},
|
|
248
|
-
|
|
249
224
|
extractAttributes(modelClass, resourceHash) {
|
|
250
225
|
let attributes = {};
|
|
251
|
-
|
|
252
226
|
if (resourceHash.attributes) {
|
|
253
|
-
modelClass.eachAttribute(
|
|
227
|
+
modelClass.eachAttribute(key => {
|
|
254
228
|
let attributeKey = this.keyForAttribute(key, 'deserialize');
|
|
255
229
|
if (resourceHash.attributes[attributeKey] !== undefined) {
|
|
256
230
|
attributes[key] = resourceHash.attributes[attributeKey];
|
|
257
231
|
}
|
|
258
|
-
if (
|
|
232
|
+
if (macroCondition(isDevelopingApp())) {
|
|
259
233
|
if (resourceHash.attributes[attributeKey] === undefined && resourceHash.attributes[key] !== undefined) {
|
|
260
|
-
assert(
|
|
261
|
-
`Your payload for '${modelClass.modelName}' contains '${key}', but your serializer is setup to look for '${attributeKey}'. This is most likely because Ember Data's JSON API serializer dasherizes attribute keys by default. You should subclass JSONAPISerializer and implement 'keyForAttribute(key) { return key; }' to prevent Ember Data from customizing your attribute keys.`,
|
|
262
|
-
false
|
|
263
|
-
);
|
|
234
|
+
assert(`Your payload for '${modelClass.modelName}' contains '${key}', but your serializer is setup to look for '${attributeKey}'. This is most likely because Ember Data's JSON API serializer dasherizes attribute keys by default. You should subclass JSONAPISerializer and implement 'keyForAttribute(key) { return key; }' to prevent Ember Data from customizing your attribute keys.`, false);
|
|
264
235
|
}
|
|
265
236
|
}
|
|
266
237
|
});
|
|
267
238
|
}
|
|
268
|
-
|
|
269
239
|
return attributes;
|
|
270
240
|
},
|
|
271
|
-
|
|
272
241
|
/**
|
|
273
242
|
Returns a relationship formatted as a JSON-API "relationship object".
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
@method extractRelationship
|
|
243
|
+
http://jsonapi.org/format/#document-resource-object-relationships
|
|
244
|
+
@method extractRelationship
|
|
278
245
|
@public
|
|
279
246
|
@param {Object} relationshipHash
|
|
280
247
|
@return {Object}
|
|
@@ -283,27 +250,20 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
283
250
|
if (typeOf(relationshipHash.data) === 'object') {
|
|
284
251
|
relationshipHash.data = this._normalizeRelationshipDataHelper(relationshipHash.data);
|
|
285
252
|
}
|
|
286
|
-
|
|
287
253
|
if (Array.isArray(relationshipHash.data)) {
|
|
288
254
|
let ret = new Array(relationshipHash.data.length);
|
|
289
|
-
|
|
290
255
|
for (let i = 0; i < relationshipHash.data.length; i++) {
|
|
291
256
|
let data = relationshipHash.data[i];
|
|
292
257
|
ret[i] = this._normalizeRelationshipDataHelper(data);
|
|
293
258
|
}
|
|
294
|
-
|
|
295
259
|
relationshipHash.data = ret;
|
|
296
260
|
}
|
|
297
|
-
|
|
298
261
|
return relationshipHash;
|
|
299
262
|
},
|
|
300
|
-
|
|
301
263
|
/**
|
|
302
264
|
Returns the resource's relationships formatted as a JSON-API "relationships object".
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
@method extractRelationships
|
|
265
|
+
http://jsonapi.org/format/#document-resource-object-relationships
|
|
266
|
+
@method extractRelationships
|
|
307
267
|
@public
|
|
308
268
|
@param {Object} modelClass
|
|
309
269
|
@param {Object} resourceHash
|
|
@@ -311,7 +271,6 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
311
271
|
*/
|
|
312
272
|
extractRelationships(modelClass, resourceHash) {
|
|
313
273
|
let relationships = {};
|
|
314
|
-
|
|
315
274
|
if (resourceHash.relationships) {
|
|
316
275
|
modelClass.eachRelationship((key, relationshipMeta) => {
|
|
317
276
|
let relationshipKey = this.keyForRelationship(key, relationshipMeta.kind, 'deserialize');
|
|
@@ -319,23 +278,15 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
319
278
|
let relationshipHash = resourceHash.relationships[relationshipKey];
|
|
320
279
|
relationships[key] = this.extractRelationship(relationshipHash);
|
|
321
280
|
}
|
|
322
|
-
if (
|
|
323
|
-
if (
|
|
324
|
-
|
|
325
|
-
resourceHash.relationships[key] !== undefined
|
|
326
|
-
) {
|
|
327
|
-
assert(
|
|
328
|
-
`Your payload for '${modelClass.modelName}' contains '${key}', but your serializer is setup to look for '${relationshipKey}'. This is most likely because Ember Data's JSON API serializer dasherizes relationship keys by default. You should subclass JSONAPISerializer and implement 'keyForRelationship(key) { return key; }' to prevent Ember Data from customizing your relationship keys.`,
|
|
329
|
-
false
|
|
330
|
-
);
|
|
281
|
+
if (macroCondition(isDevelopingApp())) {
|
|
282
|
+
if (resourceHash.relationships[relationshipKey] === undefined && resourceHash.relationships[key] !== undefined) {
|
|
283
|
+
assert(`Your payload for '${modelClass.modelName}' contains '${key}', but your serializer is setup to look for '${relationshipKey}'. This is most likely because Ember Data's JSON API serializer dasherizes relationship keys by default. You should subclass JSONAPISerializer and implement 'keyForRelationship(key) { return key; }' to prevent Ember Data from customizing your relationship keys.`, false);
|
|
331
284
|
}
|
|
332
285
|
}
|
|
333
286
|
});
|
|
334
287
|
}
|
|
335
|
-
|
|
336
288
|
return relationships;
|
|
337
289
|
},
|
|
338
|
-
|
|
339
290
|
/**
|
|
340
291
|
@method _extractType
|
|
341
292
|
@param {Model} modelClass
|
|
@@ -346,15 +297,12 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
346
297
|
_extractType(modelClass, resourceHash) {
|
|
347
298
|
return this.modelNameFromPayloadKey(resourceHash.type);
|
|
348
299
|
},
|
|
349
|
-
|
|
350
300
|
/**
|
|
351
301
|
Dasherizes and singularizes the model name in the payload to match
|
|
352
302
|
the format Ember Data uses internally for the model name.
|
|
353
|
-
|
|
354
|
-
For example the key `posts` would be converted to `post` and the
|
|
303
|
+
For example the key `posts` would be converted to `post` and the
|
|
355
304
|
key `studentAssesments` would be converted to `student-assesment`.
|
|
356
|
-
|
|
357
|
-
@method modelNameFromPayloadKey
|
|
305
|
+
@method modelNameFromPayloadKey
|
|
358
306
|
@public
|
|
359
307
|
@param {String} key
|
|
360
308
|
@return {String} the model's modelName
|
|
@@ -362,14 +310,11 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
362
310
|
modelNameFromPayloadKey(key) {
|
|
363
311
|
return singularize(dasherize(key));
|
|
364
312
|
},
|
|
365
|
-
|
|
366
313
|
/**
|
|
367
314
|
Converts the model name to a pluralized version of the model name.
|
|
368
|
-
|
|
369
|
-
For example `post` would be converted to `posts` and
|
|
315
|
+
For example `post` would be converted to `posts` and
|
|
370
316
|
`student-assesment` would be converted to `student-assesments`.
|
|
371
|
-
|
|
372
|
-
@method payloadKeyFromModelName
|
|
317
|
+
@method payloadKeyFromModelName
|
|
373
318
|
@public
|
|
374
319
|
@param {String} modelName
|
|
375
320
|
@return {String}
|
|
@@ -377,51 +322,42 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
377
322
|
payloadKeyFromModelName(modelName) {
|
|
378
323
|
return pluralize(modelName);
|
|
379
324
|
},
|
|
380
|
-
|
|
381
325
|
normalize(modelClass, resourceHash) {
|
|
382
326
|
if (resourceHash.attributes) {
|
|
383
327
|
this.normalizeUsingDeclaredMapping(modelClass, resourceHash.attributes);
|
|
384
328
|
}
|
|
385
|
-
|
|
386
329
|
if (resourceHash.relationships) {
|
|
387
330
|
this.normalizeUsingDeclaredMapping(modelClass, resourceHash.relationships);
|
|
388
331
|
}
|
|
389
|
-
|
|
390
332
|
let data = {
|
|
391
333
|
id: this.extractId(modelClass, resourceHash),
|
|
392
334
|
type: this._extractType(modelClass, resourceHash),
|
|
393
335
|
attributes: this.extractAttributes(modelClass, resourceHash),
|
|
394
|
-
relationships: this.extractRelationships(modelClass, resourceHash)
|
|
336
|
+
relationships: this.extractRelationships(modelClass, resourceHash)
|
|
395
337
|
};
|
|
396
|
-
|
|
397
338
|
this.applyTransforms(modelClass, data.attributes);
|
|
398
|
-
|
|
399
|
-
|
|
339
|
+
return {
|
|
340
|
+
data
|
|
341
|
+
};
|
|
400
342
|
},
|
|
401
|
-
|
|
402
343
|
/**
|
|
403
344
|
`keyForAttribute` can be used to define rules for how to convert an
|
|
404
345
|
attribute name in your model to a key in your JSON.
|
|
405
346
|
By default `JSONAPISerializer` follows the format used on the examples of
|
|
406
347
|
http://jsonapi.org/format and uses dashes as the word separator in the JSON
|
|
407
348
|
attribute keys.
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
Example
|
|
412
|
-
|
|
413
|
-
```app/serializers/application.js
|
|
349
|
+
This behaviour can be easily customized by extending this method.
|
|
350
|
+
Example
|
|
351
|
+
```app/serializers/application.js
|
|
414
352
|
import JSONAPISerializer from '@ember-data/serializer/json-api';
|
|
415
353
|
import { dasherize } from '<app-name>/utils/string-utils';
|
|
416
|
-
|
|
417
|
-
export default class ApplicationSerializer extends JSONAPISerializer {
|
|
354
|
+
export default class ApplicationSerializer extends JSONAPISerializer {
|
|
418
355
|
keyForAttribute(attr, method) {
|
|
419
356
|
return dasherize(attr).toUpperCase();
|
|
420
357
|
}
|
|
421
358
|
}
|
|
422
359
|
```
|
|
423
|
-
|
|
424
|
-
@method keyForAttribute
|
|
360
|
+
@method keyForAttribute
|
|
425
361
|
@public
|
|
426
362
|
@param {String} key
|
|
427
363
|
@param {String} method
|
|
@@ -430,23 +366,18 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
430
366
|
keyForAttribute(key, method) {
|
|
431
367
|
return dasherize(key);
|
|
432
368
|
},
|
|
433
|
-
|
|
434
369
|
/**
|
|
435
370
|
`keyForRelationship` can be used to define a custom key when
|
|
436
371
|
serializing and deserializing relationship properties.
|
|
437
372
|
By default `JSONAPISerializer` follows the format used on the examples of
|
|
438
373
|
http://jsonapi.org/format and uses dashes as word separators in
|
|
439
374
|
relationship properties.
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
Example
|
|
444
|
-
|
|
445
|
-
```app/serializers/post.js
|
|
375
|
+
This behaviour can be easily customized by extending this method.
|
|
376
|
+
Example
|
|
377
|
+
```app/serializers/post.js
|
|
446
378
|
import JSONAPISerializer from '@ember-data/serializer/json-api';
|
|
447
379
|
import { underscore } from '<app-name>/utils/string-utils';
|
|
448
|
-
|
|
449
|
-
export default class ApplicationSerializer extends JSONAPISerializer {
|
|
380
|
+
export default class ApplicationSerializer extends JSONAPISerializer {
|
|
450
381
|
keyForRelationship(key, relationship, method) {
|
|
451
382
|
return underscore(key);
|
|
452
383
|
}
|
|
@@ -462,28 +393,21 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
462
393
|
keyForRelationship(key, typeClass, method) {
|
|
463
394
|
return dasherize(key);
|
|
464
395
|
},
|
|
465
|
-
|
|
466
396
|
/**
|
|
467
397
|
Called when a record is saved in order to convert the
|
|
468
398
|
record into JSON.
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
```app/models/comment.js
|
|
399
|
+
For example, consider this model:
|
|
400
|
+
```app/models/comment.js
|
|
473
401
|
import Model, { attr, belongsTo } from '@ember-data/model';
|
|
474
|
-
|
|
475
|
-
export default class CommentModel extends Model {
|
|
402
|
+
export default class CommentModel extends Model {
|
|
476
403
|
@attr title;
|
|
477
404
|
@attr body;
|
|
478
|
-
|
|
479
|
-
@belongsTo('user', { async: false, inverse: null })
|
|
405
|
+
@belongsTo('user', { async: false, inverse: null })
|
|
480
406
|
author;
|
|
481
407
|
}
|
|
482
408
|
```
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
```javascript
|
|
409
|
+
The default serialization would create a JSON-API resource object like:
|
|
410
|
+
```javascript
|
|
487
411
|
{
|
|
488
412
|
"data": {
|
|
489
413
|
"type": "comments",
|
|
@@ -502,131 +426,99 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
502
426
|
}
|
|
503
427
|
}
|
|
504
428
|
```
|
|
505
|
-
|
|
506
|
-
By default, attributes are passed through as-is, unless
|
|
429
|
+
By default, attributes are passed through as-is, unless
|
|
507
430
|
you specified an attribute type (`attr('date')`). If
|
|
508
431
|
you specify a transform, the JavaScript value will be
|
|
509
432
|
serialized when inserted into the attributes hash.
|
|
510
|
-
|
|
511
|
-
Belongs-to relationships are converted into JSON-API
|
|
433
|
+
Belongs-to relationships are converted into JSON-API
|
|
512
434
|
resource identifier objects.
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
`serialize` takes an options hash with a single option:
|
|
435
|
+
## IDs
|
|
436
|
+
`serialize` takes an options hash with a single option:
|
|
517
437
|
`includeId`. If this option is `true`, `serialize` will,
|
|
518
438
|
by default include the ID in the JSON object it builds.
|
|
519
|
-
|
|
520
|
-
The JSONAPIAdapter passes in `includeId: true` when serializing a record
|
|
439
|
+
The JSONAPIAdapter passes in `includeId: true` when serializing a record
|
|
521
440
|
for `createRecord` or `updateRecord`.
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
Your server may expect data in a different format than the
|
|
441
|
+
## Customization
|
|
442
|
+
Your server may expect data in a different format than the
|
|
526
443
|
built-in serialization format.
|
|
527
|
-
|
|
528
|
-
In that case, you can implement `serialize` yourself and
|
|
444
|
+
In that case, you can implement `serialize` yourself and
|
|
529
445
|
return data formatted to match your API's expectations, or override
|
|
530
446
|
the invoked adapter method and do the serialization in the adapter directly
|
|
531
447
|
by using the provided snapshot.
|
|
532
|
-
|
|
533
|
-
If your API's format differs greatly from the JSON:API spec, you should
|
|
448
|
+
If your API's format differs greatly from the JSON:API spec, you should
|
|
534
449
|
consider authoring your own adapter and serializer instead of extending
|
|
535
450
|
this class.
|
|
536
|
-
|
|
537
|
-
```app/serializers/post.js
|
|
451
|
+
```app/serializers/post.js
|
|
538
452
|
import JSONAPISerializer from '@ember-data/serializer/json-api';
|
|
539
|
-
|
|
540
|
-
export default class PostSerializer extends JSONAPISerializer {
|
|
453
|
+
export default class PostSerializer extends JSONAPISerializer {
|
|
541
454
|
serialize(snapshot, options) {
|
|
542
455
|
let json = {
|
|
543
456
|
POST_TTL: snapshot.attr('title'),
|
|
544
457
|
POST_BDY: snapshot.attr('body'),
|
|
545
458
|
POST_CMS: snapshot.hasMany('comments', { ids: true })
|
|
546
459
|
};
|
|
547
|
-
|
|
548
|
-
if (options.includeId) {
|
|
460
|
+
if (options.includeId) {
|
|
549
461
|
json.POST_ID_ = snapshot.id;
|
|
550
462
|
}
|
|
551
|
-
|
|
552
|
-
return json;
|
|
463
|
+
return json;
|
|
553
464
|
}
|
|
554
465
|
}
|
|
555
466
|
```
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
If you want to define a serializer for your entire
|
|
467
|
+
## Customizing an App-Wide Serializer
|
|
468
|
+
If you want to define a serializer for your entire
|
|
560
469
|
application, you'll probably want to use `eachAttribute`
|
|
561
470
|
and `eachRelationship` on the record.
|
|
562
|
-
|
|
563
|
-
```app/serializers/application.js
|
|
471
|
+
```app/serializers/application.js
|
|
564
472
|
import JSONAPISerializer from '@ember-data/serializer/json-api';
|
|
565
473
|
import { underscore, singularize } from '<app-name>/utils/string-utils';
|
|
566
|
-
|
|
567
|
-
export default class ApplicationSerializer extends JSONAPISerializer {
|
|
474
|
+
export default class ApplicationSerializer extends JSONAPISerializer {
|
|
568
475
|
serialize(snapshot, options) {
|
|
569
476
|
let json = {};
|
|
570
|
-
|
|
571
|
-
snapshot.eachAttribute((name) => {
|
|
477
|
+
snapshot.eachAttribute((name) => {
|
|
572
478
|
json[serverAttributeName(name)] = snapshot.attr(name);
|
|
573
479
|
});
|
|
574
|
-
|
|
575
|
-
snapshot.eachRelationship((name, relationship) => {
|
|
480
|
+
snapshot.eachRelationship((name, relationship) => {
|
|
576
481
|
if (relationship.kind === 'hasMany') {
|
|
577
482
|
json[serverHasManyName(name)] = snapshot.hasMany(name, { ids: true });
|
|
578
483
|
}
|
|
579
484
|
});
|
|
580
|
-
|
|
581
|
-
if (options.includeId) {
|
|
485
|
+
if (options.includeId) {
|
|
582
486
|
json.ID_ = snapshot.id;
|
|
583
487
|
}
|
|
584
|
-
|
|
585
|
-
return json;
|
|
488
|
+
return json;
|
|
586
489
|
}
|
|
587
490
|
}
|
|
588
|
-
|
|
589
|
-
function serverAttributeName(attribute) {
|
|
491
|
+
function serverAttributeName(attribute) {
|
|
590
492
|
return underscore(attribute).toUpperCase();
|
|
591
493
|
}
|
|
592
|
-
|
|
593
|
-
function serverHasManyName(name) {
|
|
494
|
+
function serverHasManyName(name) {
|
|
594
495
|
return serverAttributeName(singularize(name)) + '_IDS';
|
|
595
496
|
}
|
|
596
497
|
```
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
```javascript
|
|
498
|
+
This serializer will generate JSON that looks like this:
|
|
499
|
+
```javascript
|
|
601
500
|
{
|
|
602
501
|
"TITLE": "Rails is omakase",
|
|
603
502
|
"BODY": "Yep. Omakase.",
|
|
604
503
|
"COMMENT_IDS": [ "1", "2", "3" ]
|
|
605
504
|
}
|
|
606
505
|
```
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
If you just want to do some small tweaks on the default JSON:API formatted response,
|
|
506
|
+
## Tweaking the Default Formatting
|
|
507
|
+
If you just want to do some small tweaks on the default JSON:API formatted response,
|
|
611
508
|
you can call `super.serialize` first and make the tweaks
|
|
612
509
|
on the returned object.
|
|
613
|
-
|
|
614
|
-
```app/serializers/post.js
|
|
510
|
+
```app/serializers/post.js
|
|
615
511
|
import JSONAPISerializer from '@ember-data/serializer/json-api';
|
|
616
|
-
|
|
617
|
-
export default class PostSerializer extends JSONAPISerializer {
|
|
512
|
+
export default class PostSerializer extends JSONAPISerializer {
|
|
618
513
|
serialize(snapshot, options) {
|
|
619
514
|
let json = super.serialize(...arguments);
|
|
620
|
-
|
|
621
|
-
json.data.attributes.subject = json.data.attributes.title;
|
|
515
|
+
json.data.attributes.subject = json.data.attributes.title;
|
|
622
516
|
delete json.data.attributes.title;
|
|
623
|
-
|
|
624
|
-
return json;
|
|
517
|
+
return json;
|
|
625
518
|
}
|
|
626
519
|
}
|
|
627
520
|
```
|
|
628
|
-
|
|
629
|
-
@method serialize
|
|
521
|
+
@method serialize
|
|
630
522
|
@public
|
|
631
523
|
@param {Snapshot} snapshot
|
|
632
524
|
@param {Object} options
|
|
@@ -635,72 +527,59 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
635
527
|
serialize(snapshot, options) {
|
|
636
528
|
let data = this._super(...arguments);
|
|
637
529
|
data.type = this.payloadKeyFromModelName(snapshot.modelName);
|
|
638
|
-
|
|
639
|
-
|
|
530
|
+
return {
|
|
531
|
+
data
|
|
532
|
+
};
|
|
640
533
|
},
|
|
641
|
-
|
|
642
534
|
serializeAttribute(snapshot, json, key, attribute) {
|
|
643
535
|
let type = attribute.type;
|
|
644
|
-
|
|
645
536
|
if (this._canSerialize(key)) {
|
|
646
537
|
json.attributes = json.attributes || {};
|
|
647
|
-
|
|
648
538
|
let value = snapshot.attr(key);
|
|
649
539
|
if (type) {
|
|
650
540
|
let transform = this.transformFor(type);
|
|
651
541
|
value = transform.serialize(value, attribute.options);
|
|
652
542
|
}
|
|
653
|
-
|
|
654
543
|
let schema = this.store.modelFor(snapshot.modelName);
|
|
655
544
|
let payloadKey = this._getMappedKey(key, schema);
|
|
656
|
-
|
|
657
545
|
if (payloadKey === key) {
|
|
658
546
|
payloadKey = this.keyForAttribute(key, 'serialize');
|
|
659
547
|
}
|
|
660
|
-
|
|
661
548
|
json.attributes[payloadKey] = value;
|
|
662
549
|
}
|
|
663
550
|
},
|
|
664
|
-
|
|
665
551
|
serializeBelongsTo(snapshot, json, relationship) {
|
|
666
552
|
let key = relationship.key;
|
|
667
|
-
|
|
668
553
|
if (this._canSerialize(key)) {
|
|
669
554
|
let belongsTo = snapshot.belongsTo(key);
|
|
670
555
|
let belongsToIsNotNew = belongsTo && !belongsTo.isNew;
|
|
671
|
-
|
|
672
556
|
if (belongsTo === null || belongsToIsNotNew) {
|
|
673
557
|
json.relationships = json.relationships || {};
|
|
674
|
-
|
|
675
558
|
let schema = this.store.modelFor(snapshot.modelName);
|
|
676
559
|
let payloadKey = this._getMappedKey(key, schema);
|
|
677
560
|
if (payloadKey === key) {
|
|
678
561
|
payloadKey = this.keyForRelationship(key, 'belongsTo', 'serialize');
|
|
679
562
|
}
|
|
680
|
-
|
|
681
563
|
let data = null;
|
|
682
564
|
if (belongsTo) {
|
|
683
565
|
let payloadType = this.payloadKeyFromModelName(belongsTo.modelName);
|
|
684
|
-
|
|
685
566
|
data = {
|
|
686
567
|
type: payloadType,
|
|
687
|
-
id: belongsTo.id
|
|
568
|
+
id: belongsTo.id
|
|
688
569
|
};
|
|
689
570
|
}
|
|
690
|
-
|
|
691
|
-
|
|
571
|
+
json.relationships[payloadKey] = {
|
|
572
|
+
data
|
|
573
|
+
};
|
|
692
574
|
}
|
|
693
575
|
}
|
|
694
576
|
},
|
|
695
|
-
|
|
696
577
|
serializeHasMany(snapshot, json, relationship) {
|
|
697
578
|
let key = relationship.key;
|
|
698
|
-
|
|
699
579
|
if (this.shouldSerializeHasMany(snapshot, key, relationship)) {
|
|
700
580
|
let hasMany = snapshot.hasMany(key);
|
|
701
581
|
if (hasMany !== undefined) {
|
|
702
582
|
json.relationships = json.relationships || {};
|
|
703
|
-
|
|
704
583
|
let schema = this.store.modelFor(snapshot.modelName);
|
|
705
584
|
let payloadKey = this._getMappedKey(key, schema);
|
|
706
585
|
if (payloadKey === key && this.keyForRelationship) {
|
|
@@ -708,55 +587,39 @@ const JSONAPISerializer = JSONSerializer.extend({
|
|
|
708
587
|
}
|
|
709
588
|
|
|
710
589
|
// only serialize has many relationships that are not new
|
|
711
|
-
let nonNewHasMany = hasMany.filter(
|
|
590
|
+
let nonNewHasMany = hasMany.filter(item => item.record && !item.record.isNew);
|
|
712
591
|
let data = new Array(nonNewHasMany.length);
|
|
713
|
-
|
|
714
592
|
for (let i = 0; i < nonNewHasMany.length; i++) {
|
|
715
593
|
let item = hasMany[i];
|
|
716
594
|
let payloadType = this.payloadKeyFromModelName(item.modelName);
|
|
717
|
-
|
|
718
595
|
data[i] = {
|
|
719
596
|
type: payloadType,
|
|
720
|
-
id: item.id
|
|
597
|
+
id: item.id
|
|
721
598
|
};
|
|
722
599
|
}
|
|
723
|
-
|
|
724
|
-
|
|
600
|
+
json.relationships[payloadKey] = {
|
|
601
|
+
data
|
|
602
|
+
};
|
|
725
603
|
}
|
|
726
604
|
}
|
|
727
|
-
}
|
|
605
|
+
}
|
|
728
606
|
});
|
|
729
|
-
|
|
730
|
-
if (DEBUG) {
|
|
607
|
+
if (macroCondition(isDevelopingApp())) {
|
|
731
608
|
JSONAPISerializer.reopen({
|
|
732
609
|
init(...args) {
|
|
733
610
|
this._super(...args);
|
|
734
|
-
|
|
735
|
-
assert(
|
|
736
|
-
`You've used the EmbeddedRecordsMixin in ${this.toString()} which is not fully compatible with the JSON:API specification. Please confirm that this works for your specific API and add \`this.isEmbeddedRecordsMixinCompatible = true\` to your serializer.`,
|
|
737
|
-
!this.isEmbeddedRecordsMixin || this.isEmbeddedRecordsMixinCompatible === true
|
|
738
|
-
);
|
|
739
|
-
|
|
611
|
+
assert(`You've used the EmbeddedRecordsMixin in ${this.toString()} which is not fully compatible with the JSON:API specification. Please confirm that this works for your specific API and add \`this.isEmbeddedRecordsMixinCompatible = true\` to your serializer.`, !this.isEmbeddedRecordsMixin || this.isEmbeddedRecordsMixinCompatible === true);
|
|
740
612
|
let constructor = this.constructor;
|
|
741
|
-
warn(
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
{
|
|
745
|
-
id: 'ds.serializer.json-api.extractMeta',
|
|
746
|
-
}
|
|
747
|
-
);
|
|
613
|
+
warn(`You've defined 'extractMeta' in ${constructor.toString()} which is not used for serializers extending JSONAPISerializer. Read more at https://api.emberjs.com/ember-data/release/classes/JSONAPISerializer on how to customize meta when using JSON API.`, this.extractMeta === JSONSerializer.prototype.extractMeta, {
|
|
614
|
+
id: 'ds.serializer.json-api.extractMeta'
|
|
615
|
+
});
|
|
748
616
|
},
|
|
749
617
|
warnMessageForUndefinedType() {
|
|
750
|
-
return (
|
|
751
|
-
'Encountered a resource object with an undefined type (resolved resource using ' +
|
|
752
|
-
this.constructor.toString() +
|
|
753
|
-
')'
|
|
754
|
-
);
|
|
618
|
+
return 'Encountered a resource object with an undefined type (resolved resource using ' + this.constructor.toString() + ')';
|
|
755
619
|
},
|
|
756
620
|
warnMessageNoModelForType(modelName, originalType, usedLookup) {
|
|
757
621
|
return `Encountered a resource object with type "${originalType}", but no model was found for model name "${modelName}" (resolved model name using '${this.constructor.toString()}.${usedLookup}("${originalType}")').`;
|
|
758
|
-
}
|
|
622
|
+
}
|
|
759
623
|
});
|
|
760
624
|
}
|
|
761
|
-
|
|
762
|
-
export default JSONAPISerializer;
|
|
625
|
+
export { JSONAPISerializer as default };
|