Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always return "included" where "include" has been requested (v1.1) #35

Open
noetix opened this issue Nov 24, 2017 · 11 comments
Open

Always return "included" where "include" has been requested (v1.1) #35

noetix opened this issue Nov 24, 2017 · 11 comments

Comments

@noetix
Copy link

noetix commented Nov 24, 2017

When requesting results with included data, the response should always have the included top-level key. The response structure should not change depending on the data sourced to generate the response.

While this rule is [now] part of the v1.1 spec, it'd be fantastic if it was implemented as is. I don't think its harmful for v1.0 spec consumers.

Rule: json-api/json-api@c762b92

@danivek
Copy link
Owner

danivek commented Nov 24, 2017

@noetix, great addition 👍

But actually, I can't know if "include" parameter has been requested or not regarding data (Maybe I'm missing something).

Maybe 2 possible ways:

  1. Adding a parameter 'include': true to extra data on serialize, so the library has the knowledge to generate the right result.
 Serializer.serialize('article', data, { 'include': true, ... });
  1. Doing it outside the library, because it not depends on the request but only on the data.
const result = Serializer.serialize('article', data);
result.included = (req.params.include && !result.included) ? [] : result.included;

@noetix @Mattii Any other ideas/suggestions ?

@noetix
Copy link
Author

noetix commented Nov 25, 2017

You're right, this is tough when you're decoupled from the incoming request.

Part of the spec is also to only include requested includes. The current implementation would return any includes in your serialized data.

With that in mind, option 1 with a minor tweak would be my preferred option. Instead of marking include as true, pass a list of resource types that should be included. That way the library can ignore included data that has not been requested.

e.g. GET /articles?include=comments

const Serializer = new JSONAPISerializer()
Serializer.register('article', articleType)
Serializer.register('author', authorType)
Serializer.register('comment', commentType)

Serializer.serialize('product', data, { 'include': ['comments'] })

In this example, any relationship data found for author would not be included. Passing in request options would be easy. You could even allow for the configuration when registering type.

@danivek
Copy link
Owner

danivek commented Nov 25, 2017

You're right, it's much better than true, but it could be more complicated if you have such deep path { 'include': ['comments.user.roles'] } to filter.

I always thought that, for your exemple, any relationship data for author would never be populated before passing the data through serializer, so it would never appeared in included. I think that it's the responsability of any database or something else to filter the wanted data before responding it (there is fewer things to manipulate, filter, etc... best performance).

Do you have such case of embedded author on article, even if it has not been requested before using the serializer ?

I will investigate further on the possibility of such option. Do you know a library that can do such filtering ?

Thanks !

@mattiloh
Copy link
Collaborator

mattiloh commented Nov 25, 2017

Interesting addition, thanks for the report @noetix!
The include: ['comments'] seems to be analoge to the possibility to whitelist attributes. But it is indeed quite complex, if we want to handle this for nested includes, too.

E.g. if the database payload for include: ['articles.comments.author'] contains (for any reasons) articles.author, too, we can't just whitelist all author resources, but we have to be sure, that it contains authors of comments, only.

The next problem is: relationship-names can differ from related resource types. E.g. an author relation is sometimes a generic resource of type user. So the whitelisting won't work with include: ['author'] (if we only want to filter the include array by resource-types).

That said, I would favour to go with a simple include: true. That makes sure, that the serializer can be conform with the spec.

@noetix
Copy link
Author

noetix commented Nov 26, 2017

Agreed.

If its going to be highly complex to filter results that the database layer shouldn't be returning then the problem should stay with the database layer.

👍 for include: true.

@danivek
Copy link
Owner

danivek commented Nov 26, 2017

I made a quick try of whitelisting includes with such include: ['articles.comments.author'] option on branch include-filter-test

Seems to be not as complex as it is.

@noetix, could you make a try, and tell me if it corresponds to your needs ?

@jamesdixon
Copy link

@danivek any movement on this? There are definitely cases where I don't want to include the data, but would still like the relationship to be present.

@EmirGluhbegovic
Copy link

EmirGluhbegovic commented Jul 20, 2018

@danivek Echoing @jamesdixon question

@danivek
Copy link
Owner

danivek commented Jul 20, 2018

@EmirGluhbegovic, I need some feedbacks on branch include-filter-test

could you make a try, and tell me if it corresponds to your needs ?

@alechirsch
Copy link
Contributor

@danivek I am also interested in this concept of whitelisting a chain of includes. Wondering what the status of this is.

@dimitrivdp
Copy link

I have now very often in my code:

const  result  = Serializer.serialize('comments', data, {});
result.included = []
res.send(result)

I would love to write

res.send(Serializer.serialize('comments', data, { included: false }))

Just because it is less code. ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants