define('ember-data/serializers/json-api', ['exports', 'ember-inflector', 'ember-data/serializers/json', 'ember-data/-private'], function (exports, _emberInflector, _json, _private) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); /** Ember Data 2.0 Serializer: In Ember Data a Serializer is used to serialize and deserialize records when they are transferred in and out of an external source. This process involves normalizing property names, transforming attribute values and serializing relationships. `JSONAPISerializer` supports the http://jsonapi.org/ spec and is the serializer recommended by Ember Data. This serializer normalizes a JSON API payload that looks like: ```app/models/player.js import DS from 'ember-data'; export default DS.Model.extend({ name: DS.attr('string'), skill: DS.attr('string'), gamesPlayed: DS.attr('number'), club: DS.belongsTo('club') }); ``` ```app/models/club.js import DS from 'ember-data'; export default DS.Model.extend({ name: DS.attr('string'), location: DS.attr('string'), players: DS.hasMany('player') }); ``` ```js { "data": [ { "attributes": { "name": "Benfica", "location": "Portugal" }, "id": "1", "relationships": { "players": { "data": [ { "id": "3", "type": "players" } ] } }, "type": "clubs" } ], "included": [ { "attributes": { "name": "Eusebio Silva Ferreira", "skill": "Rocket shot", "games-played": 431 }, "id": "3", "relationships": { "club": { "data": { "id": "1", "type": "clubs" } } }, "type": "players" } ] } ``` to the format that the Ember Data store expects. ### Customizing meta Since a JSON API Document can have meta defined in multiple locations you can use the specific serializer hooks if you need to customize the meta. One scenario would be to camelCase the meta keys of your payload. The example below shows how this could be done using `normalizeArrayResponse` and `extractRelationship`. ```app/serializers/application.js export default JSONAPISerializer.extend({ normalizeArrayResponse(store, primaryModelClass, payload, id, requestType) { let normalizedDocument = this._super(...arguments); // Customize document meta normalizedDocument.meta = camelCaseKeys(normalizedDocument.meta); return normalizedDocument; }, extractRelationship(relationshipHash) { let normalizedRelationship = this._super(...arguments); // Customize relationship meta normalizedRelationship.meta = camelCaseKeys(normalizedRelationship.meta); return normalizedRelationship; } }); ``` @since 1.13.0 @class JSONAPISerializer @namespace DS @extends DS.JSONSerializer */ var JSONAPISerializer = _json.default.extend({ _normalizeDocumentHelper: function _normalizeDocumentHelper(documentHash) { if (Ember.typeOf(documentHash.data) === 'object') { documentHash.data = this._normalizeResourceHelper(documentHash.data); } else if (Array.isArray(documentHash.data)) { var ret = new Array(documentHash.data.length); for (var i = 0; i < documentHash.data.length; i++) { var data = documentHash.data[i]; ret[i] = this._normalizeResourceHelper(data); } documentHash.data = ret; } if (Array.isArray(documentHash.included)) { var _ret = new Array(); for (var _i = 0; _i < documentHash.included.length; _i++) { var included = documentHash.included[_i]; var normalized = this._normalizeResourceHelper(included); if (normalized !== null) { // can be null when unknown type is encountered _ret.push(normalized); } } documentHash.included = _ret; } return documentHash; }, _normalizeRelationshipDataHelper: function _normalizeRelationshipDataHelper(relationshipDataHash) { if ((0, _private.isEnabled)("ds-payload-type-hooks")) { var modelName = this.modelNameFromPayloadType(relationshipDataHash.type); var deprecatedModelNameLookup = this.modelNameFromPayloadKey(relationshipDataHash.type); if (modelName !== deprecatedModelNameLookup && this._hasCustomModelNameFromPayloadKey()) { (true && !(false) && Ember.deprecate("You are using modelNameFromPayloadKey to normalize the type for a relationship. This has been deprecated in favor of modelNameFromPayloadType", false, { id: 'ds.json-api-serializer.deprecated-model-name-for-relationship', until: '3.0.0' })); modelName = deprecatedModelNameLookup; } relationshipDataHash.type = modelName; } else { relationshipDataHash.type = this.modelNameFromPayloadKey(relationshipDataHash.type); } return relationshipDataHash; }, _normalizeResourceHelper: function _normalizeResourceHelper(resourceHash) { (true && !(!Ember.isNone(resourceHash.type)) && Ember.assert(this.warnMessageForUndefinedType(), !Ember.isNone(resourceHash.type), { id: 'ds.serializer.type-is-undefined' })); var modelName = void 0, usedLookup = void 0; if ((0, _private.isEnabled)("ds-payload-type-hooks")) { modelName = this.modelNameFromPayloadType(resourceHash.type); var deprecatedModelNameLookup = this.modelNameFromPayloadKey(resourceHash.type); usedLookup = 'modelNameFromPayloadType'; if (modelName !== deprecatedModelNameLookup && this._hasCustomModelNameFromPayloadKey()) { (true && !(false) && Ember.deprecate("You are using modelNameFromPayloadKey to normalize the type for a resource. This has been deprecated in favor of modelNameFromPayloadType", false, { id: 'ds.json-api-serializer.deprecated-model-name-for-resource', until: '3.0.0' })); modelName = deprecatedModelNameLookup; usedLookup = 'modelNameFromPayloadKey'; } } else { modelName = this.modelNameFromPayloadKey(resourceHash.type); usedLookup = 'modelNameFromPayloadKey'; } if (!this.store._hasModelFor(modelName)) { (true && Ember.warn(this.warnMessageNoModelForType(modelName, resourceHash.type, usedLookup), false, { id: 'ds.serializer.model-for-type-missing' })); return null; } var modelClass = this.store._modelFor(modelName); var serializer = this.store.serializerFor(modelName); var _serializer$normalize = serializer.normalize(modelClass, resourceHash), data = _serializer$normalize.data; return data; }, pushPayload: function pushPayload(store, payload) { var normalizedPayload = this._normalizeDocumentHelper(payload); if ((0, _private.isEnabled)('ds-pushpayload-return')) { return store.push(normalizedPayload); } else { store.push(normalizedPayload); } }, _normalizeResponse: function _normalizeResponse(store, primaryModelClass, payload, id, requestType, isSingle) { var normalizedPayload = this._normalizeDocumentHelper(payload); return normalizedPayload; }, normalizeQueryRecordResponse: function normalizeQueryRecordResponse() { var normalized = this._super.apply(this, arguments); (true && !(!Array.isArray(normalized.data)) && Ember.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), { id: 'ds.serializer.json-api.queryRecord-array-response' })); return normalized; }, extractAttributes: function extractAttributes(modelClass, resourceHash) { var _this = this; var attributes = {}; if (resourceHash.attributes) { modelClass.eachAttribute(function (key) { var attributeKey = _this.keyForAttribute(key, 'deserialize'); if (resourceHash.attributes[attributeKey] !== undefined) { attributes[key] = resourceHash.attributes[attributeKey]; } if (true) { if (resourceHash.attributes[attributeKey] === undefined && resourceHash.attributes[key] !== undefined) { (true && !(false) && Ember.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)); } } }); } return attributes; }, extractRelationship: function extractRelationship(relationshipHash) { if (Ember.typeOf(relationshipHash.data) === 'object') { relationshipHash.data = this._normalizeRelationshipDataHelper(relationshipHash.data); } if (Array.isArray(relationshipHash.data)) { var ret = new Array(relationshipHash.data.length); for (var i = 0; i < relationshipHash.data.length; i++) { var data = relationshipHash.data[i]; ret[i] = this._normalizeRelationshipDataHelper(data); } relationshipHash.data = ret; } return relationshipHash; }, extractRelationships: function extractRelationships(modelClass, resourceHash) { var _this2 = this; var relationships = {}; if (resourceHash.relationships) { modelClass.eachRelationship(function (key, relationshipMeta) { var relationshipKey = _this2.keyForRelationship(key, relationshipMeta.kind, 'deserialize'); if (resourceHash.relationships[relationshipKey] !== undefined) { var relationshipHash = resourceHash.relationships[relationshipKey]; relationships[key] = _this2.extractRelationship(relationshipHash); } if (true) { if (resourceHash.relationships[relationshipKey] === undefined && resourceHash.relationships[key] !== undefined) { (true && !(false) && Ember.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)); } } }); } return relationships; }, _extractType: function _extractType(modelClass, resourceHash) { if ((0, _private.isEnabled)("ds-payload-type-hooks")) { var modelName = this.modelNameFromPayloadType(resourceHash.type); var deprecatedModelNameLookup = this.modelNameFromPayloadKey(resourceHash.type); if (modelName !== deprecatedModelNameLookup && this._hasCustomModelNameFromPayloadKey()) { (true && !(false) && Ember.deprecate("You are using modelNameFromPayloadKey to normalize the type for a polymorphic relationship. This has been deprecated in favor of modelNameFromPayloadType", false, { id: 'ds.json-api-serializer.deprecated-model-name-for-polymorphic-type', until: '3.0.0' })); modelName = deprecatedModelNameLookup; } return modelName; } else { return this.modelNameFromPayloadKey(resourceHash.type); } }, modelNameFromPayloadKey: function modelNameFromPayloadKey(key) { return (0, _emberInflector.singularize)((0, _private.normalizeModelName)(key)); }, payloadKeyFromModelName: function payloadKeyFromModelName(modelName) { return (0, _emberInflector.pluralize)(modelName); }, normalize: function normalize(modelClass, resourceHash) { if (resourceHash.attributes) { this.normalizeUsingDeclaredMapping(modelClass, resourceHash.attributes); } if (resourceHash.relationships) { this.normalizeUsingDeclaredMapping(modelClass, resourceHash.relationships); } var data = { id: this.extractId(modelClass, resourceHash), type: this._extractType(modelClass, resourceHash), attributes: this.extractAttributes(modelClass, resourceHash), relationships: this.extractRelationships(modelClass, resourceHash) }; this.applyTransforms(modelClass, data.attributes); return { data: data }; }, keyForAttribute: function keyForAttribute(key, method) { return Ember.String.dasherize(key); }, keyForRelationship: function keyForRelationship(key, typeClass, method) { return Ember.String.dasherize(key); }, serialize: function serialize(snapshot, options) { var data = this._super.apply(this, arguments); var payloadType = void 0; if ((0, _private.isEnabled)("ds-payload-type-hooks")) { payloadType = this.payloadTypeFromModelName(snapshot.modelName); var deprecatedPayloadTypeLookup = this.payloadKeyFromModelName(snapshot.modelName); if (payloadType !== deprecatedPayloadTypeLookup && this._hasCustomPayloadKeyFromModelName()) { (true && !(false) && Ember.deprecate("You used payloadKeyFromModelName to customize how a type is serialized. Use payloadTypeFromModelName instead.", false, { id: 'ds.json-api-serializer.deprecated-payload-type-for-model', until: '3.0.0' })); payloadType = deprecatedPayloadTypeLookup; } } else { payloadType = this.payloadKeyFromModelName(snapshot.modelName); } data.type = payloadType; return { data: data }; }, serializeAttribute: function serializeAttribute(snapshot, json, key, attribute) { var type = attribute.type; if (this._canSerialize(key)) { json.attributes = json.attributes || {}; var value = snapshot.attr(key); if (type) { var transform = this.transformFor(type); value = transform.serialize(value, attribute.options); } var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key) { payloadKey = this.keyForAttribute(key, 'serialize'); } json.attributes[payloadKey] = value; } }, serializeBelongsTo: function serializeBelongsTo(snapshot, json, relationship) { var key = relationship.key; if (this._canSerialize(key)) { var belongsTo = snapshot.belongsTo(key); if (belongsTo !== undefined) { json.relationships = json.relationships || {}; var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key) { payloadKey = this.keyForRelationship(key, 'belongsTo', 'serialize'); } var data = null; if (belongsTo) { var payloadType = void 0; if ((0, _private.isEnabled)("ds-payload-type-hooks")) { payloadType = this.payloadTypeFromModelName(belongsTo.modelName); var deprecatedPayloadTypeLookup = this.payloadKeyFromModelName(belongsTo.modelName); if (payloadType !== deprecatedPayloadTypeLookup && this._hasCustomPayloadKeyFromModelName()) { (true && !(false) && Ember.deprecate("You used payloadKeyFromModelName to serialize type for belongs-to relationship. Use payloadTypeFromModelName instead.", false, { id: 'ds.json-api-serializer.deprecated-payload-type-for-belongs-to', until: '3.0.0' })); payloadType = deprecatedPayloadTypeLookup; } } else { payloadType = this.payloadKeyFromModelName(belongsTo.modelName); } data = { type: payloadType, id: belongsTo.id }; } json.relationships[payloadKey] = { data: data }; } } }, serializeHasMany: function serializeHasMany(snapshot, json, relationship) { var key = relationship.key; var shouldSerializeHasMany = '_shouldSerializeHasMany'; if ((0, _private.isEnabled)("ds-check-should-serialize-relationships")) { shouldSerializeHasMany = 'shouldSerializeHasMany'; } if (this[shouldSerializeHasMany](snapshot, key, relationship)) { var hasMany = snapshot.hasMany(key); if (hasMany !== undefined) { json.relationships = json.relationships || {}; var payloadKey = this._getMappedKey(key, snapshot.type); if (payloadKey === key && this.keyForRelationship) { payloadKey = this.keyForRelationship(key, 'hasMany', 'serialize'); } var data = new Array(hasMany.length); for (var i = 0; i < hasMany.length; i++) { var item = hasMany[i]; var payloadType = void 0; if ((0, _private.isEnabled)("ds-payload-type-hooks")) { payloadType = this.payloadTypeFromModelName(item.modelName); var deprecatedPayloadTypeLookup = this.payloadKeyFromModelName(item.modelName); if (payloadType !== deprecatedPayloadTypeLookup && this._hasCustomPayloadKeyFromModelName()) { (true && !(false) && Ember.deprecate("You used payloadKeyFromModelName to serialize type for belongs-to relationship. Use payloadTypeFromModelName instead.", false, { id: 'ds.json-api-serializer.deprecated-payload-type-for-has-many', until: '3.0.0' })); payloadType = deprecatedPayloadTypeLookup; } } else { payloadType = this.payloadKeyFromModelName(item.modelName); } data[i] = { type: payloadType, id: item.id }; } json.relationships[payloadKey] = { data: data }; } } } }); /** @module ember-data */ if ((0, _private.isEnabled)("ds-payload-type-hooks")) { JSONAPISerializer.reopen({ modelNameFromPayloadType: function modelNameFromPayloadType(type) { return (0, _emberInflector.singularize)((0, _private.normalizeModelName)(type)); }, payloadTypeFromModelName: function payloadTypeFromModelName(modelName) { return (0, _emberInflector.pluralize)(modelName); }, _hasCustomModelNameFromPayloadKey: function _hasCustomModelNameFromPayloadKey() { return this.modelNameFromPayloadKey !== JSONAPISerializer.prototype.modelNameFromPayloadKey; }, _hasCustomPayloadKeyFromModelName: function _hasCustomPayloadKeyFromModelName() { return this.payloadKeyFromModelName !== JSONAPISerializer.prototype.payloadKeyFromModelName; } }); } if (true) { JSONAPISerializer.reopen({ willMergeMixin: function willMergeMixin(props) { var constructor = this.constructor; (true && Ember.warn('You\'ve defined \'extractMeta\' in ' + constructor.toString() + ' which is not used for serializers extending JSONAPISerializer. Read more at https://emberjs.com/api/data/classes/DS.JSONAPISerializer.html#toc_customizing-meta on how to customize meta when using JSON API.', Ember.isNone(props.extractMeta) || props.extractMeta === _json.default.prototype.extractMeta, { id: 'ds.serializer.json-api.extractMeta' })); (true && Ember.warn('The JSONAPISerializer does not work with the EmbeddedRecordsMixin because the JSON API spec does not describe how to format embedded resources.', !props.isEmbeddedRecordsMixin, { id: 'ds.serializer.embedded-records-mixin-not-supported' })); }, warnMessageForUndefinedType: function warnMessageForUndefinedType() { return 'Encountered a resource object with an undefined type (resolved resource using ' + this.constructor.toString() + ')'; }, warnMessageNoModelForType: function warnMessageNoModelForType(modelName, originalType, usedLookup) { 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 + '")\').'; } }); } exports.default = JSONAPISerializer; });