jsonapi-converter
jsonapi-converter copied to clipboard
Relationship parsing logic relies on optional resource linkage
Summary
In RelationshipResolver, the method isCollection(JsonNode)
is used a priori to determine whether or not a relationship link will return an array or an object. This cannot be done a priori if resource linkages (optional per the JSON API spec) are absent from a relationship.
See this test, which fails on develop
.
Example JSON
If the jsonapi-converter is parsing the JSON below, and attempts resolve the related
relationship (http://example.com/articles/1/comments
):
{
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON API paints my bikeshed!"
},
"relationships": {
"comments": {
"links": {
"related": "http://example.com/articles/1/comments"
}
}
}
}]
}
And the JSON returned by http://example.com/articles/1/comments
is this:
{
"data": [
{
"type": "comments",
"id": "5",
"attributes": {
"body": "First!"
}
},
{
"type": "comments",
"id": "12",
"attributes": {
"body": "I like XML better"
}
}
]
}
Parsing of the http://example.com/articles/1/comments
response will fail. Note that there is no resource linkage in the initial JSON document (the one representing articles
). Had the initial JSON document contained a resource linkage in the comments
relationship like so:
"relationships": {
"comments": {
"links": {
"related": "http://example.com/articles/1/comments"
},
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
}
}
Parsing of the http://example.com/articles/1/comments
document would succeed.
Because resource linkages are optional per the specification, the initial JSON document, sans resource linkage, should result in a successful response.
Discussion
isCollection(JsonNode)
introspects on the relationship object and uses the resource linkage as hint (resource linkages for relationships must properly represent to-many relationships as arrays, and to-one relationships as objects).
However, resource linkages are not required to be present in a relationship:
A “relationship object” MUST contain at least one of the following:
links: a links object containing at least one of the following:
* self: a link for the relationship itself (a “relationship link”). This link allows the client to directly manipulate the relationship. For example, removing an author through an article’s relationship URL would disconnect the person from the article without deleting the people resource itself. When fetched successfully, this link returns the linkage for the related resources as its primary data. (See Fetching Relationships.)
* related: a related resource link
data: resource linkage
meta: a meta object that contains non-standard meta-information about the relationship.
So resource linkages, if present, may be used a priori to determine the to-many or to-one-ness of a relationship, but if the resource linkage is not present, then the parsing logic must be prepared to parse a collection or an object after dereferencing the relationship.
69b1945 contains a unit test demonstrating the issue.