jsonapi-serializer icon indicating copy to clipboard operation
jsonapi-serializer copied to clipboard

3.6.6 breaks deep relations

Open ev8dev opened this issue 5 years ago • 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"
         }
      }
   ]
}

ev8dev avatar Jan 16 '20 12:01 ev8dev

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) {
...

danielpigott avatar Jan 23 '20 01:01 danielpigott

up

Roriz avatar Mar 02 '20 19:03 Roriz

up

kln avatar Mar 06 '20 16:03 kln

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.

ev8dev avatar Apr 23 '20 11:04 ev8dev

So support for this library has been down. I've been recently going around the other serializers checking for people who are looking for a better serializer. Over the past few days I've designed a resource-recursive, typescript/javascript library for serializing the entire JSON:API spec. You might want to check it out if this library doesn't fix the recursion :)

Link: https://github.com/jun-sheaf/ts-japi

jrandolf avatar May 20 '20 17:05 jrandolf

@danielpigott @ev8dev @kln @Roriz So I have been going around looking for those who are struggling to find a proper JSONAPI serializer.

Over the past few days I've designed a resource-recursive, typescript/javascript library for serializing the entire JSON:API spec. Our API is far more fluent (and obvious) than the one here (and every other serializer I have seen/used). If this serializer doesn't fit your need, you might want to check it out :) Development is active.

If you are in particular struggling with issues such as links, resource relationships, and deep recursion (essentially any of the complicated parts of the JSON:API spec), I strongly recommend moving to our library.

{TS:JAPI}: https://github.com/jun-sheaf/ts-japi

jrandolf avatar May 21 '20 02:05 jrandolf