neomerx / json-api

Framework agnostic JSON API (jsonapi.org) implementation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Include paths and fieldsets

neomerx opened this issue · comments

This issue is about the following questions

  • what should we do if include contradicts fieldset
  • removing relationship with resource identities breaks full linkage and might make the data non-sense.

The question above will be explained in details and illustrated by examples below

The test data have the following structure

`Site` (1)
  |_ `Posts` (1)
        |_ `Author` (1)
        |_ `Comment` (2) + each comment has a relationship with the same `Author` above

in JSON API format those data look like this

1-level deep include paths (filter attributes and relationships)

We are trying to emulate the following resource request and the question is what should be in output

GET /sites/1?include=posts&fields[sites]=name&fields[posts]=title,comments

In the URL above there is a contradiction. From one side we say we want field name in output but not field posts for Site. On another side we expect posts to be in output.
The request above will produce

{
    "data":{
        "type":"sites",
        "id":"2",
        "attributes":{
            "name":"site name"
        },
        "links":{
            "self":"http://example.com/sites/2"
        }
    }
}

if field posts is in URL

GET /sites/1?include=posts&fields[sites]=name,posts&fields[posts]=title,comments

it will produce

{
    "data" : {
        "type" : "sites",
        "id"   : "2",
        "attributes" : {
            "name" : "site name"
        },
        "relationships" : {
            "posts" : {
                "data" : [
                    { "type" : "posts", "id" : "1" }
                ]
            }
        },
        "links" : {
            "self" : "http://example.com/sites/2"
        }
    },
    "included" : [
        {
            "type" : "posts",
            "id"   : "1",
            "attributes" : {
                "title" : "JSON API paints my bikeshed!"
            },
            "relationships" : {
                "comments" : {
                    "data" : [
                        { "type" : "comments", "id" : "5" },
                        { "type" : "comments", "id" : "12" }
                    ]
                }
            }
        }
    ]
}

Possible solution for the contradiction in

GET /sites/1?include=posts&fields[sites]=name&fields[posts]=title,comments

would be something like (relationship posts disappear but posts present in included, but would it mean if we have relationships as my-posts, favorite-posts, friends-posts or just relationships with polymorphic data...)

{
    "data" : {
        "type" : "sites",
        "id"   : "2",
        "attributes" : {
            "name" : "site name"
        },
        "links" : {
            "self" : "http://example.com/sites/2"
        }
    },
    "included" : [
        {
            "type" : "posts",
            "id"   : "1",
            "attributes" : {
                "title" : "JSON API paints my bikeshed!"
            },
            "relationships" : {
                "comments" : {
                    "data" : [
                        { "type" : "comments", "id" : "5" },
                        { "type" : "comments", "id" : "12" }
                    ]
                }
            }
        }
    ]
}

Test code is here

2-level deep include paths

It has the same set of open questions

  • what should we do if include says include but fieldset says not to include or vice versa
  • removing relationship with resource identities breaks full linkage and might make the data non-sense.

An example of 2 level include could be found here

There seems to be a bit of a bug right now in your implementation.

If you do something like this:

GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1

It seems that authors are not included in the (present) neomerx response because the fields are not specified in "fields[articles]"

When actually authors are supposed to be included, but the relationships should not be displayed (in the articles resource).

Please see this discussion on jsonapi's discussion board regarding this very issue below:

http://discuss.jsonapi.org/t/sparse-fieldsets-and-relationships/294/5

@mmucklo I think you are not correct. In @ethanresnick comment it states it should have author field

GET /articles?include=author&fields[articles]=title,body,author&fields[people]=name HTTP/1.1

As far as I know (and tested) this lib works exactly this way.

@ethanresnick Thanks for the comment. It seems this issue is almost resolved. The only remaining uncertain part is what if JSON API reply has 2 relationships with same type resources (e.g. new and deleted items). If we include those relationships and drop full linkage requirement how the client app can handle such a reply? Probably instead of must drop full linkage it should be might drop?

I think I've finally realized how it should work 😄 and fixed it. Will be released in 0.7.0

The test is here \Neomerx\Tests\JsonApi\Encoder\EncodeSparseAndFieldSetsTest::testIncludeAndSparseFieldSetsInGreedyMode