tobyzerner / json-api-php

JSON-API (http://jsonapi.org) responses in PHP.
MIT License
436 stars 79 forks source link

Exclude "attributes" section from response #98

Closed PinkTiu closed 8 years ago

PinkTiu commented 8 years ago

Hey,

first of all, thanks for this amazing library.

I have a problem with returning a correct response for a relationship self link. Consider a resource object "Course". A "Course" can have a to many relationship the resource object "Participant".

So for example a GET to the URL "/courses/1" will return:

GET: http://example.com/courses/1

{
    "data": {
        "type": "course",
        "id": "1",
        "attributes": {
            "title": "My Course Title"
        },
        "relationships": {
            "participants": {
                "links": {
                     "self": "http://example.com/courses/1/relationships/participants",
                     "related": "http://example.com/curses/1/participants"
                },
                "data": [
                    { "type": "participant", "id": "5" },
                    { "type": "participant", "id": "12" }
                ]
            }
        }
    }
}

The response of the related link is easy to achieve. But the self link makes some problems. According to the link http://discuss.jsonapi.org/t/relation-link-usage/149/2 it should be returned the following:

GET: http://example.com/courses/1/relationships/participants

{ 
    "data": [{
        "type": "participant",
        "id": "5" 
      }, {
        "type": "participant",
        "id": "12" 
      }]
}

I can only achieve this response:

GET: http://example.com/courses/1/relationships/participants

{ 
    "data": [{
        "type": "participant",
        "id": "5",
        "attributes": []
      }, {
        "type": "participant",
        "id": "12" ,
        "attributes": []
      }]
}

To do so, I have written a new Serializer which returns null when getAttributes() is called. But this doesn't exclude the "attributes" array. I haven't found a way to do so. Maybe there is one, so please give me a hint.

Even if there is a way, it would be the best not to write a new Serializer at all. Maybe the following is a good idea:

$collection = new Collection($participants, 'participant');
$document = new Document($collection);
return response($document, 200)

$participants contains the two participants with id 5 and 12. The second parameter of new Collection contains the string which will be used as type in the resulting json (same function as the $type variable in AbstractSerializer).

UserComponent commented 8 years ago

Same issue here. It seems as if this was intended to be implemented, but there is a missing conditional in: \Tobscure\JsonApi\Resource::toArray().

This is a quick fix by adding the if (!$this->isIdentifier()) before the $array['attributes'] = $this->getAttributes(); statement ~line 75. It checks if the constructor was intended to be a resource-identifier-object (i.e., you fed the constructor the id (string), and not an array/object of data).

With that in place, you can get the right format (and still with the original serializer):

$participants = ["1", "2", "3", ...];
$collection = new Collection($participants, new ParticipantSerializer());
$document = new Document($collection);
return response($document, 200);

That way, we avoid duplication of serializer classes for the identifiers/resources of the same types.