fractal icon indicating copy to clipboard operation
fractal copied to clipboard

JsonApiSerializer doesnt conform the specs for fetching relationship urls

Open leemason opened this issue 9 years ago • 11 comments

i think this needs a whole resource type tbh but im sure they may be other ways too.

take this example:

/api/users/1?include=user_meta

This works great, and the data is formatted as expected.

however as per the spec each included/related resource has its own links which MUST be satisfyable as per the spec at:

/api/users/1/user_meta /api/users/1/relationships/user_meta

The serializer does an amazing job of generating those links and requires nothing on our end to complete (which made me drool the first time i used it).

no lets satisfy either of those urls:

/api/users/1/user_meta

in my code, i have something like this:

//$meta is a collection of models (laravel)
$meta = functiontofetchusermetabyid($id);

return Fractal\Resource\Collection($meta, UserMetaTransformer::class, $this->type);

this will return something like this:

{
    "data":[
        {
             "type":"user_meta",
             "id":"1",
             "attributes":[..the atts...],
             "links":{
                  "self":"\/api\/user_meta\/1"
             }
         }
    ]
}

however this isnt what the spec says, it should look like this:

{
  "links": {
    "self": "/users/1/relationships/user_meta",
    "related": "/users/1/user_meta"
  },
  "data": [
    { "type": "user_meta", "id": "1" },
    { "type": "user_meta", "id": "2" }
  ]
}

There are a few issues here:

  1. it should have a top level links object
  2. resource objects shouldnt have any attributes
  3. resource objects shouldnt have a links object

Ive reread the docs a few times, and its not right:

A "resource identifier object" MUST contain type and id members.

A "resource identifier object" MAY also include a meta member, whose value is a meta object that contains non-standard meta-information.

there are other places in the docs that it also mentions nothing about including resources for these requests at all, so basically the response should only contain:

  1. a data object with nested resource objects
  2. a links object containing the current link and related link.

Im currently having to prepare a custom response and not use fractal for this, but it would be great if it was possible.

Todo so i propose the addition of a new resource type, currently there are:

  1. null resource
  2. item resource
  3. collection resource

The new resource type should be a relationship resource

I think this would be need to implemented as a resource class, in the scope class, and then within the serializers as well, but looking at it, it doesnt look overly hard to implement.

Then we could all use:

$resource = new Fractal\Resource\Relationship($books, new BookTransformer, 'books');

which would format the data as expected.

Im happy to have a go at making a pull request for this if you agree this is a needed addition.

leemason avatar Nov 12 '15 15:11 leemason

just a few more notes:

the transformer used could be any existing or new transformer, but in reality all it needs to do is return either an item resource with an id, or a collection resource with an id.

Any other data returned would just be ignored.

optimally a transformer which only proccessed the item by returning its id would be favourable, but re-using an existing transformer for the item would (shouldnt) break anything as all we need is the id key returned in the array.

We could enforce this via interfaces, but even though its favourable to have a different transformer for optimisation this should be left down the end user.

leemason avatar Nov 12 '15 15:11 leemason

I agree completely with this, I'm adding it to my todo list right now

willishq avatar Nov 15 '15 11:11 willishq

@willishq Oh, yes. There are critical troubles with relationships :(

  1. I simply can't include ONLY relationships links into object. For example, I have countries and cities, I don't want to include thousands of cities in country payload, but I should include a top-level relationships field with links to nested city resources (e.g. /countries/1/cities). Now there is no possibility for that
  2. Even when base url for serializer is provided and relations are included, relation does not contain links:
data: [
{
  type: "countries",
  id: "19",
  attributes: {
  name: "Австралия",
    currency_code: "AUD",
    currency: "Австралийский доллар"
},
  links: {
    self: "http://desk.nalivator.app/countries/19"
  },
  relationships: {
    cities: {
      data: [
        {
          type: "cities",
          id: "3979034"
        }
      ]
    }
  }
}

],
included: [

This makes almost impossible to work with relationships with spec-fullfilling clients (like ember.js for example)

terion-name avatar Dec 25 '15 09:12 terion-name

Is there any update on this? I am attempting to implement an API following the JSON-API spec and have hit this road block with Fractal.

simonbowen avatar Jan 08 '16 22:01 simonbowen

Same here, would be very interested in knowing how this is getting along. @willishq?

lukasoppermann avatar Feb 21 '16 17:02 lukasoppermann

Any news on this?

jonaholsson avatar Mar 12 '16 00:03 jonaholsson

I'm also interested about any news on this?

roberttolton avatar Nov 14 '16 14:11 roberttolton

At the risk of necro-ing an old issue, i'm guessing that since this issue is 3 years old now that this is a dead issue?

martinmike2 avatar Apr 06 '18 17:04 martinmike2

At this point I believe it won't happen, sadly.

JC5 avatar Jun 20 '18 19:06 JC5

Any updates?

jimdelois avatar Oct 28 '20 15:10 jimdelois

This issue has been automatically marked as stale because it has not had recent activity. It will be closed after 4 weeks if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 16 '22 06:04 stale[bot]