diff --git a/lib/deserializer-utils.js b/lib/deserializer-utils.js index 1265fd4..b06796e 100644 --- a/lib/deserializer-utils.js +++ b/lib/deserializer-utils.js @@ -6,6 +6,9 @@ var _extend = require('lodash/extend'); var _transform = require('lodash/transform'); var Inflector = require('./inflector'); +const ancestrySeparator = ":"; +const idSeparator = ";"; + module.exports = function (jsonapi, data, opts) { var alreadyIncluded = []; @@ -36,7 +39,7 @@ module.exports = function (jsonapi, data, opts) { if (included) { // To prevent circular references, check if the record type // has already been processed in this thread - if (ancestry.indexOf(included.type) > -1) { + if (ancestry.indexOf(included.type + idSeparator) > -1) { return Promise .all([extractAttributes(included)]) .then(function (results) { @@ -47,7 +50,7 @@ module.exports = function (jsonapi, data, opts) { } return Promise - .all([extractAttributes(included), extractRelationships(included, ancestry + ':' + included.type + included.id)]) + .all([extractAttributes(included), extractRelationships(included, ancestry + ancestrySeparator + included.type + idSeparator + included.id)]) .then(function (results) { var attributes = results[0]; var relationships = results[1]; @@ -146,7 +149,7 @@ module.exports = function (jsonapi, data, opts) { this.perform = function () { return Promise - .all([extractAttributes(data), extractRelationships(data, data.type + data.id)]) + .all([extractAttributes(data), extractRelationships(data, data.type + ancestrySeparator + data.id)]) .then(function (results) { var attributes = results[0]; var relationships = results[1]; diff --git a/test/deserializer.js b/test/deserializer.js index bd5ae42..bcda428 100644 --- a/test/deserializer.js +++ b/test/deserializer.js @@ -1394,6 +1394,55 @@ describe('JSON API Deserializer', function () { }); }); }); + + describe("With relationships using similar type names", function () { + it("should return all data without circular error", function (done) { + var dataSet = { + data: { + type: "productsearch", + id: "47", + attributes: { + sku: "7TY55", + }, + relationships: { + product: { data: { type: "products", id: "122" } }, + }, + }, + included: [ + { + type: "images", + id: "49", + attributes: { + mimeType: "image/jpeg", + }, + relationships: { + product: { data: { type: "products", id: "122" } }, + }, + }, + { + type: "products", + id: "122", + attributes: { + sku: "7TY55" + }, + relationships: { + image: { data: { type: "images", id: "49" } }, + }, + }, + ], + }; + + new JSONAPIDeserializer().deserialize(dataSet, function (err, json) { + expect(json).to.be.an('object').with.keys('id', 'sku', 'product'); + expect(json.product).to.exist; + expect(json.product).to.be.an('object').with.keys('id', 'sku', 'image'); + expect(json.product.image).to.exist; + expect(json.product.image).to.be.an('object').with.keys('id', 'mime-type', 'product'); + + done(null, json); + }); + }); + }); }); describe('without callback', function () {