SeyZ / jsonapi-serializer

A Node.js framework agnostic library for (de)serializing your data to JSON API
MIT License
736 stars 197 forks source link

Deserialization does not work on repeated included relationships #173

Open rfblue2 opened 6 years ago

rfblue2 commented 6 years ago

If there are relationships that share resources, and are included only once each (see the example below - there are only two books but one is both a "selling" and a "favorite") when they are deserialized the second instance of the repeated relationship is not properly included (it just places null)

{
    "data": {
        "type": "user",
        "id": "5ad2601522c6f6733408ae1f",
        "attributes": {...},
        "relationships": {
            "favorite": {
                "data": [
                    {
                        "type": "book",
                        "id": "5aca58621d13177065279691"
                    }
                ]
            },
            "selling": {
                "data": [
                    {
                        "type": "book",
                        "id": "5ac8dd784f904b5a281aa061"
                    },
                    {
                        "type": "book",
                        "id": "5aca58621d13177065279691"
                    }
                ]
            }
        }
    },
    "included": [
        {
            "type": "book",
            "id": "5aca58621d13177065279691",
            "attributes": {...},
        },
        {
            "type": "book",
            "id": "5ac8dd784f904b5a281aa061",
            "attributes": {...}
        }
    ]
}

When deserialized, this returns

{
  ...
  "id": "5ad2601522c6f6733408ae1f",
  "selling": [
    {
      ...
      "id": "5ac8dd784f904b5a281aa061"
    },
    null <-- Relationship was included but presumably used up for something else!
  ],
  "favorite": [
    {
      ...
      "id": "5aca58621d13177065279691"
    }
  ]
}
AELSchauer commented 6 years ago

This is a known issue with this repo but the author hasn't done anything to publicly address it. I forked this repo to fix this issue. You can view the PR here: https://github.com/SeyZ/jsonapi-serializer/pull/170

And you can view my fork here: https://github.com/AELSchauer/jsonapi-serializer

shupac commented 6 years ago

just ran into this issue. @AELSchauer I checked out your branch but it wasn't working for me

SeyZ commented 6 years ago

I'm currently trying to reproduce this issue on my side and everything looks fine:

    describe('FOO', function () {
      it('should return all data without circular error', function (done) {
        var dataSet = {
          data: {
            type: 'users',
            id: '54735750e16638ba1eee59cb',
            attributes: { 'first-name': 'Sandro', 'last-name': 'Munda' },
            relationships: {
              favorite: {
                data: [{
                  type: 'book',
                  id: '5aca58621d13177065279691'
                }]
              },
              selling: {
                data: [{
                  type: 'book',
                  id: '5ac8dd784f904b5a281aa061'
                }, {
                  type: 'book',
                  id: '5aca58621d13177065279691'
                }]
              }
            }
          },
          included: [{
            type: 'book',
            id: '5ac8dd784f904b5a281aa061',
            attributes: {
              'book-title': 'Tesla, SpaceX.',
              isbn: '978-0062301239'
            }
          }, {
            type: 'book',
            id: '5aca58621d13177065279691',
            attributes: {
              'book-title': 'Steve Jobs',
              isbn: '978-1451648546'
            }
          }]
        };

        new JSONAPIDeserializer()
         .deserialize(dataSet, function (err, json) {
           console.log(json);
           done(null, json);
         });
      });
    });

OUTPUT:

{ 'first-name': 'Sandro',
  'last-name': 'Munda',
  id: '54735750e16638ba1eee59cb',
  favorite: 
   [ { 'book-title': 'Steve Jobs',
       isbn: '978-1451648546',
       id: '5aca58621d13177065279691' } ],
  selling: 
   [ { 'book-title': 'Tesla, SpaceX.',
       isbn: '978-0062301239',
       id: '5ac8dd784f904b5a281aa061' },
     { 'book-title': 'Steve Jobs',
       isbn: '978-1451648546',
       id: '5aca58621d13177065279691' } ] }

Any help to reproduce ?

vovkvlad commented 5 years ago

I have a pretty similar issue, but without null - it just does not include nested relationship for the second time - it's just omitted. It looks that as if it has already used it for the first time, and in the second time - it's not there. Reroducible code is here: https://codesandbox.io/s/jsonapiserializer-bug-wez5c?fontsize=14

konovalov-nk commented 5 years ago

Can confirm. Just spent ~6 hours figuring this out + 2 hours on adapting solution by @AELSchauer (thanks a lot!). Glad this issue was already pointed out or I'd have to spend even more time thinking I've gone mad 😄

Basically, having circular dependencies on your resources is not possible due to references evaluated as null.

A simple example would be the following JSONAPI response:

{
   "data": {
      "type": "product",
      "id": "1",
      "attributes": {
         "name": "Product 1"
      },
      "relationships": {
         "related": {
            "data": [
               {
                  "type": "product",
                  "id": "2"
               }
            ]
         }
      }
   },
   "included": [
      {
         "type": "product",
         "id": "2",
         "attributes": {
            "name": "Product 2"
         },
         "relationships": {
            "related": {
               "data": [
                  {
                     "type": "product",
                     "id": "1"
                  }
               ]
            }
         }
      }
   ]
}

https://github.com/SeyZ/jsonapi-serializer/commit/4e7001663493e124040de228349e1ac4e6ba0890 without a patch produces following result:

{
  "name": "Product 1",
  "id": "1",
  "related": [
    {
      "name": "Product 2",
      "id": "2",
      "related": [
        null
      ]
    }
  ]
}

Demonstration available here.