SeyZ/jsonapi-serializer

3.6.6 breaks deep relations

ev8dev opened this issue ยท 4 comments

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

Expected result

  • profiles
    • layouts-profiles
      • grid
      • elements-layouts-profiles
        • elements
          • icons
          • actions-elements
            • actions
            • events

Actual result

  • profiles
    • layouts-profiles
      • grid
      • elements-layouts-profiles
        • elements

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"
         }
      }
   ]
}

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

up

kln commented

up

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.