Comments (13)
I think I have to put your mind to some of the nuances of what is the data and how it could and should be processed. You need to understand them before pushing a 'solution'.
Suppose we want to encode a person and a few his/her comments. Let's consider a couple of possible JSON API document and answer what kind of data we need in relationships. Spoiler: it's more than either nothing or the full resource.
No Data in Relationship
{
"data": {
"type" : "people",
"id" : "9",
"attributes" : {
"first_name" : "Dan",
"last_name" : "Gebhardt"
},
"relationships" : {
"comments" : {
"links" : {
"self" : "http://example.com/people/9/relationships/comments",
"related" : "http://example.com/people/9/comments"
}
}
},
"links" : {
"self" : "http://example.com/people/9"
}
}
}
No data in relationship needed. Currently it corresponds to self::RELATIONSHIP_DATA
omitted.
Some Data in non-included Relationship
{
"data": {
"type" : "people",
"id" : "9",
"attributes" : {
"first_name" : "Dan",
"last_name" : "Gebhardt"
},
"relationships" : {
"comments" : {
"data": [
{ "type" : "comments", "id" : "1" },
{ "type" : "comments", "id" : "2" }
],
"links" : {
"self" : "http://example.com/people/9/relationships/comments",
"related" : "http://example.com/people/9/comments"
}
}
},
"links" : {
"self" : "http://example.com/people/9"
}
}
}
Identity data in the relationship are needed. Even if we do not include the relationship we do need some data from it. Please think about it again. Even if the relationship is not included we do need some data from it. Though it's only type and id.
Thus hiding all the data behind Closure will not work. The encoder will have to execute the closure to get that type and id even if doesn't need all the rest.
Currently, it corresponds to self::RELATIONSHIP_DATA
filled with Neomerx\JsonApi\Contracts\Schema\IdentifierInterface
objects or full resources.
All Data in included Relationship
Same as above plus included section with full data (type, id, attributes, relationships).
Full data in a relationship are needed.
Currently, it corresponds to self::RELATIONSHIP_DATA
filled with full resources.
from json-api.
Yes I totally agree with those, but you're missing a scenario (which is what this issue is about): data only if related resource is included.
So the four scenarios are:
- No data in relationship - schema does not return data.
- Data in non-included relationship - schema returns the identifiers
- Data in included relationship - schema returns the related resources.
- Data only if relationship is included (i.e. the relationship will definitely be parsed by the parser) - returned resources need to be wrapped in a closure and only parsed if the parser is parsing the relationship.
(4) corresponded to SELF::SHOW_DATA
and SELF::DATA
in v1/v2, in v3 it corresponds to SELF::RELATIONSHIP_DATA
plus the $isShouldParse
.
I'm in total agreement with 1-3, but none of 1 to 3 match our use case of the encoder. So this issue is about supporting that missing scenario. It forms 100% of our use case and is supported by other server-side encoding libraries.
from json-api.
If you do not want to provide any identifiers in relationships but links only, you can add support for SHOW_DATA
between these two lines. It might be something like
if (\array_key_exists(BaseCustomSchema::RELATIONSHIP_HAS_DATA, $description) === true &&
$description[BaseCustomSchema::RELATIONSHIP_HAS_DATA] === false
) {
unset($description[BaseCustomSchema::RELATIONSHIP_DATA]);
}
from json-api.
- No data in relationship - schema does not return data.
Could be achieved either by omitting RELATIONSHIP_DATA
or by RELATIONSHIP_HAS_DATA
set to false as shown above.
- Data in non-included relationship - schema returns the identifiers
Could be achieved with IdentifierInterface
.
- Data in included relationship - schema returns the related resources.
Typical usage. Just return full resource in RELATIONSHIP_DATA
.
- Data only if relationship is included (i.e. the relationship will definitely be parsed by the parser) - returned resources need to be wrapped in a closure and only parsed if the parser is parsing the relationship.
If you want identifiers then it's 2) or 3) though only identifiers will be used in relationships and no resources will be added to included section.
If you do not want identifiers and only links are OK then it could be achieved either by omitting RELATIONSHIP_DATA
or by RELATIONSHIP_HAS_DATA
set to false as shown above.
from json-api.
I've updated the sample. So you can try it yourself.
from json-api.
Ok great but why not add it to this package as this is a standard JSON API approach? That's the bit I don't understand... this isn't an extension, it's a standard use-case and a totally compliant interpretation of the spec. If the point of your encoder is to be JSON API compliant, then this missing scenario needs to be added in.
If you do not want to add it in, please can you explain how we extend to gain access to the $isShouldParse
, as described at the start of this issue? The extension suggested by #236 is not the extension we need to implement. Rather than updating #236 extension, please can you show us how to do the extension described in this issue?
from json-api.
As far as I understood, you wanted to have $includeRelationships
in getRelationships()
and ability to return a Closure
in RELATIONSHIP_DATA
accompanied with RELATIONSHIP_HAS_DATA
that can prevent the closure ever been executed. Can you please confirm the solution I've shown solves your migration problem?
I would appreciate if we can agree it is a working solution and move the next topic what should and should not be included in the main code base.
from json-api.
Sorry to hear the news from your temporary message, and that is of course totally understandable and right that you'll have limited time on this package.
I'll close this issue for now.
from json-api.
@lindyhopchris Shall we continue the discussion? Do I understand it correctly, the solution does solve your problem though you think more code should be moved from extention to the main code base?
from json-api.
The solution is not ideal and we would not use it for a number of reasons.
It's injecting a runtime dependency (SchemaFields) into something that we resolve out of a service container (the schemas). We treat the schemas as a service because it allows schemas to be injected with other services via constructor dependency injection.
The SchemaFields cannot be a service because we don't know where to create them from... JSON API encoding might happen outside of a HTTP request, for example when broadcasting JSON API payloads over services such as Pusher. That's just one example of many for why we can't have the schema fields injected into the schemas in the way the solution proposes.
What the SchemaFields represents is something that the encoder knows... i.e. the fields and include paths it is being asked to encode; i.e. it's a runtime dependency of the encoder that needs to be passed around to the services (schemas) that the encoder is using.
We could easily write this as an extension except for one thing: there's next to no opportunity to hook into the code within the encoder and parser, because of the amount of private methods. Yes we can copy & paste the code to our own class, but we do not like (for good reasons) to do this - i.e. copy 100s of lines of codes just to add one or two changes. It means if you make any changes to the methods we've copied and pasted, we're out of sync.
That's the challenge we face. I think maybe though if you're busy, we bank this for the moment. We'll upgrade to v2
instead of v3
and then use that for a bit before deciding whether we go to v3
. I think we need to write the solution that actually works for our use case and then show you what that is - as it'll demonstrate how difficult it is to add extensions to the code base. It's understandably difficult for you to write a demo extension when you cannot know the ins and outs of our use cases!
from json-api.
@lindyhopchris Hi, I'd like to return to this discussion. I've currently got 2 ideas
- sending
Neomerx\JsonApi\Contracts\Parser\PositionInterface
as a second param togetRelationships
- sending a wrapper around
Neomerx\JsonApi\Contracts\Parser\PositionInterface
instead of the position.
If a position (level, path, a name of the parent relationship) is available then filtering could be done as earlier.
A wrapper gives an ability to have a custom single object that implements filtering logic instead of possibly replicating it in every schema (e.g. super fast cached filters or something similar).
What do you think?
from json-api.
Ah ok, hadn't been expecting you to suggest that.
I've banked upgrading, and probably won't be doing anything around upgrading until later this year (because of other work I've got on at the mo). My plan had been to attempt to upgrade to v3 and see where I get.
Maybe it would be better for us to revisit this at the point I do the upgrade, because it's a bit difficult to comment on what approach would be required when I'm not actually working on the upgrade?
from json-api.
OK. I'm expecting you to have difficulties with accessing filters (paths, fieldsets) from schemas. Unlike position
the encoder doesn't have filtering info where it invokes the schemas. The filters will be applied later in the upper stack.
Currently, this problem could be solved by creating schemas (objects or via closures) with filtering info and then sending the schemas to the encoder.
An elegant solution could be sending the filtering info to the schemas when EncoderInterface::withIncludedPaths
or EncoderInterface::withFieldSets
are called. Probably via SchemaContainer
.
It might require changing some interfaces so the next major version will be needed. Though the changes are likely to be minimal so most of the users migrate without any changes.
from json-api.
Related Issues (20)
- Include related resource into output in its entirety? HOT 11
- Include array of `Identifier`s HOT 5
- What's happened to include relationships in schema `getRelationships` method HOT 40
- EncoderPropertiesTrait::withIncludePaths only works with arrays HOT 1
- subUrl property is private - BaseSchema HOT 6
- [Question] How to exclude relationships on collections by default? HOT 9
- Catch exceptions from json_encode HOT 7
- Error while using BaseQueryParser and Encoder together HOT 8
- Fetch a link from an existing Element HOT 2
- How to encode custom array NOT LARAVEL MODEL INSTANCE HOT 4
- How to create nested relationships HOT 3
- sparse fields filter relationships HOT 3
- Member names are converted to kebab-case HOT 1
- stricter typing with psalm
- Relationship data generator is invoked more than once if data is empty HOT 16
- Support interface/superclass based mapping in SchemaContainer HOT 1
- How can I fix incorrect links in my `included` compound document section? HOT 1
- Problem with PHP version 8.1
- accept same type on Encoder::instance
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from json-api.