SeyZ / jsonapi-serializer

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

3.6.6 breaks deep relations #223

Open ev8dev opened 4 years ago

ev8dev commented 4 years ago

3.6.6 does not include relations deeper than the third level anymore. This worked in 3.6.5.

Expected result

Actual result

Data

{
   "data":{
      "type":"profiles",
      "id":"23",
      "attributes":{
         "name":"Apotheker",
         "created":"2019-11-19T13:16:36+00:00",
         "modified":"2019-11-19T13:16:36+00:00"
      },
      "relationships":{
         "layouts-profiles":{
            "data":[
               {
                  "type":"layouts-profiles",
                  "id":"21"
               }
            ],
            "links":{
               "self":"\/apiv1\/layouts-profiles?profile-id=23"
            }
         }
      },
      "links":{
         "self":"\/apiv1\/profiles\/23"
      }
   },
   "included":[
      {
         "type":"icons",
         "id":"9",
         "attributes":{
            "icon":"exclamation"
         },
         "links":{
            "self":"\/apiv1\/icons\/9"
         }
      },
      {
         "type":"actions",
         "id":"15",
         "attributes":{
            "action":"nextPriorityTicketInLine"
         },
         "links":{
            "self":"\/apiv1\/actions\/15"
         }
      },
      {
         "type":"events",
         "id":"1",
         "attributes":{
            "event":"mouseclickleft"
         },
         "links":{
            "self":"\/apiv1\/events\/1"
         }
      },
      {
         "type":"actions-elements",
         "id":"10",
         "relationships":{
            "action":{
               "data":{
                  "type":"actions",
                  "id":"15"
               },
               "links":{
                  "self":"\/apiv1\/actions\/15"
               }
            },
            "event":{
               "data":{
                  "type":"events",
                  "id":"1"
               },
               "links":{
                  "self":"\/apiv1\/events\/1"
               }
            }
         },
         "links":{
            "self":"\/apiv1\/actions-elements\/10"
         }
      },
      {
         "type":"events",
         "id":"11",
         "attributes":{
            "event":"totalWaitingPriorityTickets"
         },
         "links":{
            "self":"\/apiv1\/events\/11"
         }
      },
      {
         "type":"actions-elements",
         "id":"11",
         "relationships":{
            "event":{
               "data":{
                  "type":"events",
                  "id":"11"
               },
               "links":{
                  "self":"\/apiv1\/events\/11"
               }
            }
         },
         "links":{
            "self":"\/apiv1\/actions-elements\/11"
         }
      },
      {
         "type":"elements",
         "id":"2",
         "attributes":{
            "color":"f3a91f",
            "content":null,
            "content-color":"FFFFFF",
            "row-start":2,
            "col-start":0,
            "row-end":2,
            "col-end":4,
            "is-rounded":0,
            "is-dynamic":0
         },
         "relationships":{
            "icon":{
               "data":{
                  "type":"icons",
                  "id":"9"
               },
               "links":{
                  "self":"\/apiv1\/icons\/9"
               }
            },
            "actions-elements":{
               "data":[
                  {
                     "type":"actions-elements",
                     "id":"10"
                  },
                  {
                     "type":"actions-elements",
                     "id":"11"
                  }
               ],
               "links":{
                  "self":"\/apiv1\/actions-elements?element-id=2"
               }
            }
         },
         "links":{
            "self":"\/apiv1\/elements\/2"
         }
      },
      {
         "type":"elements-layouts-profiles",
         "id":"170",
         "relationships":{
            "element":{
               "data":{
                  "type":"elements",
                  "id":"2"
               },
               "links":{
                  "self":"\/apiv1\/elements\/2"
               }
            }
         },
         "links":{
            "self":"\/apiv1\/elements-layouts-profiles\/170"
         }
      },
      {
         "type":"grids",
         "id":"1",
         "attributes":{
            "width":484,
            "height":112,
            "row-count":6,
            "col-count":12
         },
         "links":{
            "self":"\/apiv1\/grids\/1"
         }
      },
      {
         "type":"layouts-profiles",
         "id":"21",
         "attributes":{
            "zoom":1
         },
         "relationships":{
            "elements-layouts-profiles":{
               "data":[
                  {
                     "type":"elements-layouts-profiles",
                     "id":"170"
                  }
               ],
               "links":{
                  "self":"\/apiv1\/elements-layouts-profiles?layout-profile-id=21"
               }
            },
            "grid":{
               "data":{
                  "type":"grids",
                  "id":"1"
               },
               "links":{
                  "self":"\/apiv1\/grids\/1"
               }
            }
         },
         "links":{
            "self":"\/apiv1\/layouts-profiles\/21"
         }
      }
   ]
}
danielpigott commented 4 years ago

I have hit the same issue, and it appears to be a problem with how the code is detecting recursive relationships. If any of the parents have types that are a substring of the child type they will be detected as a recursive relation e.g. from your example because elements-layouts-profiles contains the string elements it won't keep parsing relations.

To work around this, in deserializer utils I have updated the check to look at type and id instead of just type when detecting a recursion.

...
 function findIncluded(relationshipData, ancestry) {
...
      if (included) {
        // To prevent circular references, check if the record type
        // has already been processed in this thread
        if (ancestry.indexOf(included.type + included.id) > -1) {
...
Roriz commented 4 years ago

up

kln commented 4 years ago

up

ev8dev commented 4 years ago

I have hit the same issue, and it appears to be a problem with how the code is detecting recursive relationships. If any of the parents have types that are a substring of the child type they will be detected as a recursive relation e.g. from your example because elements-layouts-profiles contains the string elements it won't keep parsing relations.

To work around this, in deserializer utils I have updated the check to look at type and id instead of just type when detecting a recursion.

...
 function findIncluded(relationshipData, ancestry) {
...
      if (included) {
        // To prevent circular references, check if the record type
        // has already been processed in this thread
        if (ancestry.indexOf(included.type + included.id) > -1) {
...

I noticed I never replied to this, but still thanks @danielpigott.

We distribute this package onto our servers automatically so for now we're still on 3.6.5 since the issue doesn't occur there. It would be nice if this issue could be fixed in a future version so we can use the newest package.