# Same resource different attributes, Polymorphism

**URL:** <https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312>\
**Category:** Uncategorized\
**Created:** [September 28, 2021, 5:45am UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312 "2021-09-28T05:45:12Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![gusverdywid](https://avatars.discourse-cdn.com/v4/letter/g/e8c25b/32.png) [@gusverdywid](https://discuss.jsonapi.org/u/gusverdywid)\
**Post date:** [September 28, 2021, 5:45am UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/1 "2021-09-28T05:45:12Z")

</div>

Hi everyone,

I am new in this community but I have been using JSON API for a while. Though now this particular problem kinda got me wondering if I am doing the right thing.

So let say I have a `Transportation` resource on `/transportations`, a `Transportation` might have various kind of types, eg. `car`, `ship`, `plane` and so on. Each type of `Transportation` might have different attributes, for example `plane` has `wheelsNum` and `wingTypes` while `ship` has `sailsNum` and `helmRadius` while they also share some common attributes such as `maxPassenger`, `fuelType` and so on. How do we model this kind of resource?

I can imagine having this when hitting `GET /transportations`:

```auto
{
.....
  "data": [
    {
      "id":"1",
      "type":"transportation",
      "attributes":{
        "transportationType":"ship",
        "sailsNum":4,
        "helmRadius":20,
        "maxPassengers":15,
        .....other attributes.....,
      }
    },
    {
      "id":"2",
      "type":"transportation",
      "attributes":{
        "transportationType":"plane",
        "wheelsNum":7,
        "wingTypes":"....",
        "maxPassengers":50,
        .....other attributes.....,
      }
    }
  ]
.....
}

```

But that means same resource might have different attribute fields. Though I do not see it anywhere in the spec that it is prohibited (or maybe I missed it), I do not feel right this is the right thing to do just because it looks inconsistent.  
Is there a better approach? Or that one is just enough?

Thanks

---

<div class="post-metadata">

**Author:** ![fdrake](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/fdrake/32/654_2.png) [@fdrake](https://discuss.jsonapi.org/u/fdrake)\
**Post date:** [September 28, 2021, 2:57pm UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/2 "2021-09-28T14:57:26Z")

</div>

Is there any reason not to have several types of transport, each with their own `type` value, and whatever appropriate fields are useful?

-Fred

---

<div class="post-metadata">

**Author:** ![gusverdywid](https://avatars.discourse-cdn.com/v4/letter/g/e8c25b/32.png) [@gusverdywid](https://discuss.jsonapi.org/u/gusverdywid)\
**Post date:** [September 29, 2021, 6:30am UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/3 "2021-09-29T06:30:01Z")

</div>

Hi @fdrake , thank you for responding to my question.

A couple of reasons not to have several / different transport `type`:

- The client side would need to show all the transports available in the system in one page
- The number of types might grow a lot more in the future, the example I gave you was just a simplification (with different analogy) of the real problem, in the same context above it might have `bike`, `horse`, `skateboard`, `zeppelin`, `air_balloon`, … so many more
- Having the client to handle each different type of transport endpoints would mean they having a risk of missing on a new type whenever a new type is being published (less of a concern though)

---

<div class="post-metadata">

**Author:** ![fdrake](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/fdrake/32/654_2.png) [@fdrake](https://discuss.jsonapi.org/u/fdrake)\
**Post date:** [September 29, 2021, 9:48pm UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/4 "2021-09-29T21:48:04Z")

</div>

> [@gusverdywid](#):
>
> Hi @fdrake , thank you for responding to my question.
> 
> A couple of reasons not to have several / different transport `type`:
> 
> - The client side would need to show all the transports available in the system in one page

That’s up to the client, though, isn’t it? You could offer filtering by type, or whatever sort of filters make sense.

> [@gusverdywid](#):
>
> - The number of types might grow a lot more in the future, the example I gave you was just a simplification (with different analogy) of the real problem, in the same context above it might have `bike`, `horse`, `skateboard`, `zeppelin`, `air_balloon`, … so many more

Whether you use the JSON:API `type` or some internal `kind` field, that issue doesn’t change. To deal with fields that are not common across all types of transports, the client will need to understand them. `type` is nice because it’s already intended for that purpose, and any client encountering a `type` they don’t know about should be able to recognize it as something unknown (though they may not recognize it as a transport).

> [@gusverdywid](#):
>
> - Having the client to handle each different type of transport endpoints would mean they having a risk of missing on a new type whenever a new type is being published (less of a concern though)

A dynamically expanding set of types (whether `type` or an internal `kind` field) can be handled by also making available a collection of type descriptions, which can take the form of schema, that can be used to inform about displayable properties and what properties can be set on creation or update, if those are concerns for your application.

Ultimately, for a complex and expanding set of types, you need to be able to deal with out of date clients, or predict the ways in which your application is most likely to expand.

-Fred

---

<div class="post-metadata">

**Author:** ![gusverdywid](https://avatars.discourse-cdn.com/v4/letter/g/e8c25b/32.png) [@gusverdywid](https://discuss.jsonapi.org/u/gusverdywid)\
**Post date:** [September 30, 2021, 12:34pm UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/5 "2021-09-30T12:34:04Z")

</div>

> [@fdrake](#):
>
> That’s up to the client, though, isn’t it? You could offer filtering by type, or whatever sort of filters make sense.

That is true, even though the client is actually just another internal team but it is doable. All these are negotiable as long we stick to the standard.

Another thing to confirm though, since the client still needs to show all the transports within one page anyway, meaning they need to call multiple endpoints (which is fine), how would they implement filtering in that case? I cannot imagine sorting on the client side would be wise, especially when the data is huge

> [@fdrake](#):
>
> To deal with fields that are not common across all types of transports, the client will need to understand them.

Agree, eventually they need to handle all the fields differently in the “details” / “view” page of the transport

> [@fdrake](#):
>
> can be handled by also making available a collection of type descriptions, which can take the form of schema, that can be used to inform about displayable properties and what properties can be set on creation or update

Not quite sure what you mean here. Can you please point me to a link / article of this kind of pattern?

Thanks.

---

<div class="post-metadata">

**Author:** ![fdrake](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/fdrake/32/654_2.png) [@fdrake](https://discuss.jsonapi.org/u/fdrake)\
**Post date:** [September 30, 2021, 4:16pm UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/6 "2021-09-30T16:16:04Z")

</div>

> [@gusverdywid](#):
>
> Another thing to confirm though, since the client still needs to show all the transports within one page anyway, meaning they need to call multiple endpoints (which is fine), how would they implement filtering in that case? I cannot imagine sorting on the client side would be wise, especially when the data is huge

I don’t see a need for separate endpoints. Your initial question presented a `GET /transportations` endpoint that returned a collection of transportation resources. Having many types of transport types doesn’t need to change that. It becomes a collection that can contain many different kinds of transports.

It can be easy to overload the simplicity of the example URL structures in the specification with meaning, but no such constraints are present. Constraints are only attached to URLs returned by the server in particular elements of the response.

If you’re using the `filter` [query parameter family](https://jsonapi.org/format/1.1/#query-parameters-families) (to use terminology from the proposed version 1.1 of the specification), a request to retrieve a single transport type might be something like this:

`GET /transportations?filter[type]=donkey`

Selecting multiple types might then look something like this:

`GET /transportations?filter[type]=donkey,plane,starship`

That should combine nicely with any other filters and sorting parameters.

> [@gusverdywid](#):
>
> > [@fdrake](#):
> >
> > can be handled by also making available a collection of type descriptions, which can take the form of schema, that can be used to inform about displayable properties and what properties can be set on creation or update
> 
> Not quite sure what you mean here. Can you please point me to a link / article of this kind of pattern?

When I say “type descriptions”, what I mean is some sort of schema that can inform the client of the fields available for each concrete type, what the values can be, when the can be set (creation `POST`, update `PATCH`, etc.), whether they can be used to sort / filter, whatever is needed. I’m sure there are examples in the literature, and I’ve worked with such things tailored for form-building in the past, so it’s not a fresh idea. I don’t have a handy stash of links to articles on the topic, though; sorry!

-Fred

---

<div class="post-metadata">

**Author:** ![gusverdywid](https://avatars.discourse-cdn.com/v4/letter/g/e8c25b/32.png) [@gusverdywid](https://discuss.jsonapi.org/u/gusverdywid)\
**Post date:** [October 1, 2021, 7:18am UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/7 "2021-10-01T07:18:19Z")

</div>

> [@fdrake](#):
>
> I don’t see a need for separate endpoints. Your initial question presented a `GET /transportations` endpoint that returned a collection of transportation resources. Having many types of transport types doesn’t need to change that. It becomes a collection that can contain many different kinds of transports.

Ah, this is new to me. I did not know that one endpoint (eg. `/transportations`) may contain multiple type of resources. So I imagine `/transportations` will be something like the following (even with the same id as long the `type` is different)?

```auto
{
.....
  "data": [
    {
      "id":"1",
      "type":"transportation-ship",
      "attributes": {
         "sailsNum":4,
         "maxPassengers":15,
          ......other attributes......
      }
    },
    {
      "id":"1",
      "type":"transportation-plane",
      "attributes": {
          "wheelsNum":7,
          "maxPassengers":50,
          ......other attributes......
      }
    }
  ]
.....
}

```

> [@fdrake](#):
>
> If you’re using the `filter` [query parameter family](https://jsonapi.org/format/1.1/#query-parameters-families) (to use terminology from the proposed version 1.1 of the specification)

Whoops, my bad. I meant to write **sorting** not filtering. Since sorting across different endpoints might be impossible if I have to go with the multiple endpoints implementation. But don’t mind this.

It is clear now, this is exactly what I am looking for. So in summary JSON API supports multiple `type` within the same endpoints as long the same `type` value has the same attributes. Love JSON API even more now.  
Thanks man, this is valuable, appreciate it.

---

<div class="post-metadata">

**Author:** ![fdrake](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/fdrake/32/654_2.png) [@fdrake](https://discuss.jsonapi.org/u/fdrake)\
**Post date:** [October 1, 2021, 6:47pm UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/8 "2021-10-01T18:47:39Z")

</div>

I’m glad my comments have been helpful!

> [@gusverdywid](#):
>
> So I imagine `/transportations` will be something like the following (even with the same id as long the `type` is different)?

Since resource identity is based on both `type` and `id`, that can be acceptable, but you do want to think about how you’d address a specific transportation resource.

I find it helpful to think of two kinds of collections: those that “own” the resources contained, and those that only have references to resources elsewhere (think of to-many relationships). Using URL paths like **/type/id** is certainly convenient, but works best when the **id** values are unique within **/type/**. And JSON:API does not impose any requirement that positive, sequential integers are used for **id** values for each type.

How best to implement that depends very much on your persistent store and other software you’re using to build your application, of course.

-Fred

---

<div class="post-metadata">

**Author:** ![jelhan](https://sea2.discourse-cdn.com/flex016/user_avatar/discuss.jsonapi.org/jelhan/32/822_2.png) [@jelhan](https://discuss.jsonapi.org/u/jelhan)\
**Post date:** [October 4, 2021, 11:53am UTC](https://discuss.jsonapi.org/t/same-resource-different-attributes-polymorphism/2312/9 "2021-10-04T11:53:36Z")

</div>

> [@gusverdywid](#):
>
> But that means same resource might have different attribute fields. Though I do not see it anywhere in the spec that it is prohibited (or maybe I missed it), I do not feel right this is the right thing to do just because it looks inconsistent.

You are right that it is not explicitly forbidden. But it seems to go against the intend of the specification:

> § 5.2.1 Identification
> 
> […]
> 
> The `type` member is used to describe [resource objects](https://jsonapi.org/format/#document-resource-objects) that share common attributes and relationships.
> 
> [JSON:API — Latest Specification (v1.1)](https://jsonapi.org/format/#document-resource-object-identification)

Just wanted to cite the specification itself additional to the great explanation by @fdrake.
