# Relationships within abstract relationship

**URL:** <https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158>\
**Category:** Uncategorized\
**Created:** [November 20, 2017, 11:01pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158 "2017-11-20T23:01:24Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [November 20, 2017, 11:01pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/1 "2017-11-20T23:01:24Z")

</div>

Imagine the situation that you have `parking` with relationship `cars`.  
Cars relationship is an array of resources of types `sedan` or `truck`.

It’s works perfectly when you need to get parking with all the cars it contains.

`GET /parkings/{parking_id}?include=cars`

But what to do when you need to get descendant relationships of sedans & trucks resources. For sedans you need `trunk` and for trucks you need `trailer`.

`GET /parkings/{parking_id}?include=cars.trunk,cars.trailer`

`sedan` has `trunk` but don’t has `trailer` and vice versa for `truck`. Isn’t it wrong and do we need to avoid abstractions when related resources they has different relationships?

`GET /parkings/{parking_id}?include=sedans.trunk,trucks.trailer`

I understand that sometimes abstract resources could have abstract descendant relationship names, but there are cases when only one resource has relationship of name `X` and others don’t have anything similar to it.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [November 21, 2017, 8:51pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/2 "2017-11-21T20:51:53Z")

</div>

@michaelhibay sorry for calling you again, but your advices are best :}

---

<div class="post-metadata">

**Author:** ![michaelhibay](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/michaelhibay/32/405_2.png) [@michaelhibay](https://discuss.jsonapi.org/u/michaelhibay)\
**Post date:** [November 22, 2017, 9:07pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/3 "2017-11-22T21:07:36Z")

</div>

Haha, alright I’ve been busy doing conference work and starting a new job but I’ll see what I can do here to help. 😃

I’m not sure if this is the API you’re working with or a contrived example, but the problem here looks like you want the cars relationship to be polymorphic, and then utilize a feature of {json:api} which doesn’t support it.

If you [look here](http://discuss.jsonapi.org/t/relationship-uris-for-special-helper-uris/943), you’ll see some discussion from a while back where I make a bunch of points about resources not being objects.

The data shaping capabilities of {json:api} are not polymorphic, and are shaped by expected structure of the relationship hierarchy. This is OK and a really good design, as it is a motivator to keep the design simple and think about the design from another perspective.

Consider this, if you have a polymorphic ambiguous payload being returned to the consumer client, how much duplication of business logic would you expect that client to carry out? An ideal application would create a model completely reactive to the data returned, and by including this ambiguity you would _require_ your clients to tightly couple themselves to your data model to simultaneously support all response messages for your resource model.

However, if the calling agent were to filter and explicitly understand the resource representation it was going to receive, it would be much easier to make changes to any particular representation or its client side handling without the addition of cyclomatic complexity.

My suggestion would be to refactor this in some way to allow for data shaping when filtering, or break it up into multiple requests. The other option if you control the client and the consumer, is to remember you control the default shape of the data so you could simply `/parkings/{parking_id}?filter[type]=cars,trucks` to get whatever shape you want. You could make this work within spec, but I think it really exposes an underlying flaw in the API design. Resources are not objects.

I hope this helps!

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [November 22, 2017, 10:07pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/4 "2017-11-22T22:07:19Z")

</div>

Thank you for the answer, @michaelhibay! I’m hope you are doing well with your new job.

This is contrived example, for easier understanding without subject area specific vocabulary.

You are right, I’m talking about polymorphic collection which will return resources of different types, but I understand that each type could have different relations in it (they are differ, thats why they have different types). I understand that resource !== object.

By providing example `/parkings/{parking_id}?filter[type]=cars,trucks` I suppose you meant `/parkings/{parking_id}?filter[cars][type]=sedans,trucks`. Because it’s not a parking for trucks only or sedans only. It’s parking, which could contain `sedans` as well as `trucks`. Parking could have it’s own types: `open`, `underground`, `rooftop`. And if we need to get all `open` parkings with cars of type `sedan` and `truck` only:  
`/parkings/{parking_id}?filter[type]=open&filter[cars][type]=sedan,truck`.

But all this stuff isn’t solving original issue I’ve tried to explain here. If I understand you right, we should avoid to have collection of resources which will return resources of different types if their descendant relations differ from each other.

In other words:

- If `resource1` has descendant relations `child1` and `child2` and `resource2` has the same relations they could be collected into `polymorphic-relation`.
- If descendant relations are differs - `resource1` and `resource2` shouldn’t be collected into `polymorphic-relation`.
- If descendant relations are differs and `resource1` and `resource2` were collected into `polymorphic-relation` we should make extra requests to collect all relations for each item of this collection.

Did I understand you right?

---

<div class="post-metadata">

**Author:** ![michaelhibay](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/michaelhibay/32/405_2.png) [@michaelhibay](https://discuss.jsonapi.org/u/michaelhibay)\
**Post date:** [November 22, 2017, 10:48pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/5 "2017-11-22T22:48:20Z")

</div>

Thanks, so far so good!

Ok, that certainly gives me some more perspective to understand the difficulty you are talking about.

The issue I was speaking about is the data shaping of a non-uniform set of message representations. The spec is very lenient to provide you the capability to offer this type of functionality, however the more customized you get the less likely the behavior of consumers would be across the ecosystem. If you control both, you can be a bit more custom but you need to project the definition of this behavior explicitly and completely.

The ability to construct this kind of data modeling is stretching the capabilities of the simple relationship traversal mechanism. In addition to the ability to determine the default included resources for any resource, you also have the option to include the deep nested relationship links to include higher order relationships without traversal of the long chains. In your example this could be something like cars-features, where the features are the trunk / trailer …etc.

One final note, since this is a contrived example I wasn’t trying to pick apart the example itself but perhaps this could give you an idea. The definition of cars and trucks as different resources is something which is complicating the solution space, because there is similar resources which are differentiated by something other than the query parameters.

```auto
/parkings/{parking_id}?include=vehicles,vehicles.features&filter[vehicles.type]=(sedan,truck)&filter[vehicles.features.type]=(trunk,trailer)

```

The include parameter is expected to operate on a uniform set of resources, so what you can do is make the set uniform by containing the dynamic nature of the resource representations to a uniform pattern. Pass include parameter to include the features resource as well, and send only the relevant features by filtering.

Apologies if this example is a bit rushed and not completely vetted or confusing, but I’m out of time and my family is eager to begin the holiday celebrations! I hope something in here helps!

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [November 22, 2017, 11:28pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/6 "2017-11-22T23:28:40Z")

</div>

Thank you for diving deep and providing such detailed overview.

Thats very interesting idea to extract all uncommon relationships within collection to new abstract relationship and then filter it out by types you need.  
For example if all the types MUST have `wheels` it could be kept as separate relationship, but all the rest will be collected to `features` relationship. Or even keep all the parts of the `vehicle` inside this `features` relationship.

The only thing I don’t like about this solution that frontend client will be required to have 2 separate transformers for `truck` resource which was received from `/trucks?include=trailer` and one more for `truck` resource which were received from polymorphic relation `/parkings?include=vehicles,vehicles.features`. And the same for each resource type which could be located in polymorphic collection.

At the beginning I’ve thought that you offer to make something like virtual `?include=vehicle.features` parameter which will be transformed to something like `?include=sedan.trunk,truck.trailer` under the hood. In this case structure of `sedan` & `truck` resources will be consistent in any time, but this breaks json:api spec as I understand.

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [November 23, 2017, 3:29pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/7 "2017-11-23T15:29:25Z")

</div>

> [@a-komarev](#):
>
> The only thing I don’t like about this solution that frontend client will be required to have 2 separate transformers for truck resource which was received from /trucks?include=trailer and one more for truck resource which were received from polymorphic relation /parkings?include=vehicles,vehicles.features. And the same for each resource type which could be located in polymorphic collection.

The main issue with this way in my opinion - inconsistent resource structure. By the way this isn’t problem, it’s just possibility of the problem in the future. I cannot be 100% sure that it’s right or wrong, just leaving it here as a notice that more research required.

`GET /trucks?include=trailer` output:

```json
{
  "data": [{
    "type": "truck",
    "id": "vehicle-1",
    "relationships": {
      "trailer": {
        "data": {
          "type": "trailer",
          "id": "vehicle-1-trailer"
        }
      }
    }
  }]
}

```

`GET /parkings?include=vehicles,vehicles.features`

```json
{
  "data": [{
    "type": "truck",
    "id": "vehicle-1",
    "relationships": {
      "features": {
        "data": {
          "type": "trailer",
          "id": "vehicle-1-trailer"
        }
      }
    }
  }]
}

```

---

<div class="post-metadata">

**Author:** ![michaelhibay](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/michaelhibay/32/405_2.png) [@michaelhibay](https://discuss.jsonapi.org/u/michaelhibay)\
**Post date:** [November 28, 2017, 7:25am UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/8 "2017-11-28T07:25:57Z")

</div>

> [@a-komarev](#):
>
> The main issue with this way in my opinion - inconsistent resource structure. By the way this isn’t problem, it’s just possibility of the problem in the future. I cannot be 100% sure that it’s right or wrong, just leaving it here as a notice that more research required.

Why?

This could be open ended and asked in both directions, why does the structure have to be different from the two? I don’t think that is a good idea. Why is there a `/truck` resource? Shouldn’t it be `/vehicle?filter[type]=truck`, or is there some other reason? If the filter defines the truck resource well enough, why would the front end need a transformer in any other shape than the one?

Remember, resources are not objects and complex types are composed of other types so you have the latitude to define the composition format which makes most sense while serving the needs of the consumer.

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [November 29, 2017, 3:48pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/9 "2017-11-29T15:48:34Z")

</div>

I thought that creation of the trucks will be in `POST /trucks` endpoint, to have more precise relations (do not drop everything to `features` relation, but have many relations). Otherwise `POST /vehicles` endpoint handler will be very complex and hard to maintain if there will be a lot of types of vehicles, each type has it’s own collection of relations one of them required, and other don’t.

---

<div class="post-metadata">

**Author:** ![michaelhibay](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/michaelhibay/32/405_2.png) [@michaelhibay](https://discuss.jsonapi.org/u/michaelhibay)\
**Post date:** [November 29, 2017, 5:14pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/10 "2017-11-29T17:14:15Z")

</div>

Remember that {json:api} documents are typed, so a simple switch statement or dynamic handler can easily allow each type processing to be separately developed and executed based on the type attribute in the root of the compound document. No additional complexity is introduced, the URL processor is simply behaving differently for a different message.

APIs are not CRUD, your payload does not need to be in the same format all the time at the same URL. You will _always_ need to manage the ingestion of each message type, the only difference is that it isn’t at the `/truck` endpoint, instead it is at a common abstracted resource URL like `/vehicle` or `/asdfnailsdilfasdf`.

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [March 11, 2018, 9:18am UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/11 "2018-03-11T09:18:06Z")

</div>

I’ve returned back to this question while designed Conversations system.

`GET /conversations` could return different types of conversations. Each conversation type scoped by different scope types.

Candidate has an interview for a Job. It’s `JobInterview` conversation:

```auto
POST /conversations
{
  "data": {
    "type": "JobInterview",
    "relationships": {
      "scopes": {
        "data": [
          {
            "type": "Job",
            "id": "job-1"
          },
          {
            "type": "Candidate",
            "id": "candidate-1"
          }
        ]
      }
    }
  }
}

```

As you can see both of scopes are located in polymorphic `scopes` relationship. It works well when you want to add another type of conversation which requires another scope types. For example `DisputeNegotiation` conversation will require scopes of type `Dispute` and maybe `NegotiationSession` if you want to break them down daily.

It’s easy to collect the data because `GET /conversations` will return all the types of the conversations and you could filter them out. But isn’t that hard for a client to understand what scopes are required for concrete type of conversation? I don’t even know how to describe in documentation and error messages that conversation of type `JobInterview` requires 2 scopes where first one MUST be `Job` and the second one MUST be `Candidate`. And conversation of type `DisputeNegotiation` requires 2 scopes where first one MUST be `Dispute` and the second one MUST be `NegotiationSession`. Moreover there is possibility of conversations with more or less than 2 scopes.

All this things makes me feel wrong. Wouldn’t it be clearer for the client to have this API:

```auto
POST /conversations
{
  "data": {
    "type": "JobInterview",
    "relationships": {
      "job": {
        "data": {
          "type": "Job",
          "id": "job-1"
        }
      },
      "candidate" {
        "data": {
          "type": "Candidate",
          "id": "candidate-1"
        }
      }
    }
  }
}

```

Then if client want to create `DisputeNegotiation` he will have another 2 relationships: `dispute` and `session`. Then documentation and error messages will be clear and human friendly. But then we are returning to the issue which I described earlier. While getting resources from endpoint `GET /conversations` each resource type will have different relationships.

After all I’ve thought about resource creation could use concrete relations (eg. `job`, `candidate`, `dispute` and etc) and resource fetching could use concrete or abstract relationship `scopes` for the filtering purposes. Under the hood all this concrete relations will store as `scopes`. That will give client an opportunity to chose what way to use. But it’s not obvious behavior that modifying scopes will affect on concrete relationships. Then I suppose it would be better to make `scopes` relationship read only.

Isn’t it an overkill?

---

<div class="post-metadata">

**Author:** ![michaelhibay](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/michaelhibay/32/405_2.png) [@michaelhibay](https://discuss.jsonapi.org/u/michaelhibay)\
**Post date:** [March 13, 2018, 9:53pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/12 "2018-03-13T21:53:34Z")

</div>

I think the level of down the rabbit hole on the contrived example drowned out some of the more basic things I was saying, namely that the design needs to be simple to understand for the client. Not knowing the real application of your question meant I had to answer the question you were asking as best as I could guess.

With this second example, I’m getting the impression you are looking for a way to do a compound identifier within a polymorphic collection. I really don’t think the format supports (well) this kind of functionality. I think you would be better served spending your time fixing the resource model to not require this kind of processing, than to discover a way to make the format support it.

---

<div class="post-metadata">

**Author:** ![a-komarev](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/a-komarev/32/440_2.png) [@a-komarev](https://discuss.jsonapi.org/u/a-komarev)\
**Post date:** [March 14, 2018, 8:35pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/13 "2018-03-14T20:35:58Z")

</div>

I’ve thought about creating resource with type `Scope`, but it wouldn’t help much, because under the hood it will have same issue, it will require set of different relationships for different use cases.

I think that {json:api} specification not completely fit polymorphic relations at this moment and this topic should be discovered more. In my case there are a lot of endpoints where polymorphism will be possible in future.

---

<div class="post-metadata">

**Author:** ![michaelhibay](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/michaelhibay/32/405_2.png) [@michaelhibay](https://discuss.jsonapi.org/u/michaelhibay)\
**Post date:** [March 15, 2018, 5:04am UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/14 "2018-03-15T05:04:58Z")

</div>

The format is certainly not optimized for all use cases, and it is very likely you are correct. However, I’d caution you to not throw the baby out with the bathwater. The value we add in the API space is in abstracting a lot of this complexity to form a more simple uniform interface for consumers.

If this is a recurrent problem you are encountering than I think one of these two things is true:

1. {json:api} does not support your application and domain constraints well.
2. The way the services are designed can be optimized to better fit the model.

Either way, good luck I hope you find your answer!

---

<div class="post-metadata">

**Author:** ![skaaptjop](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/skaaptjop/32/619_2.png) [@skaaptjop](https://discuss.jsonapi.org/u/skaaptjop)\
**Post date:** [May 22, 2019, 4:56pm UTC](https://discuss.jsonapi.org/t/relationships-within-abstract-relationship/1158/15 "2019-05-22T16:56:41Z")

</div>

@michaelhibay this may just be a light bulb moment for me…  
Is the point you’re making here that I could POST to`/vehicles` a payload of more than one type?  
e.g. the resource posted could be:

```
{ "type": "car", "id": "123", "attributes": {...} }
or
{ "type": "truck", "id": "abc", "attributes": {...} }

```

as long as the IDs don’t clash.

If that is correct then I might finally _get it_: the resource is not the object and this allows me to mix things semantically on the API because, ultimately, the resource plus its relations defines what it is and how to deal with it.
