I am working with two resources: Buildings and Characteristics. The Characteristics stores all the definitions that a building could have. When an characteristic is applied to a building, it receives a value. For example, the “number_desks” characteristic might have a value of 5.
My question is: Can I add this relational data to the relationship resource, and is it possible to retrieve this data through a query?
Presumably you’ve gone this way because characteristics is an extensible enumeration that you want to managed via REST (POST a new characteristic)?
Are all characteristics simply counts? or do some have other attributes like colour, weight, value and so on? If it is variable, then maybe you don’t want such a generic model, but instead need to model each characteristic as a different resource type.
To your specific question, assuming characteristics is extensible and simply countable, I think you have a 3rd resource which is a “characteristic count” - which has an attribute value of “5”, a relationship to characteristic “9” and a relationship to building “4”. This link table approach means each building can have many different countable characteristics
Attributes on relationships are not supported by the JSON:API specification. Using an intermediate resource is recommended instead.
This design decision simplifies the specification and implementations. Allowing attributes in resource identifier objects used in resource linkage seems simple. But it quickly get complex if you take updating those attributes into account.
Thank you for your feedback; it is greatly appreciated.
@PeaDubYa
Indeed, my building will possess several characteristics with simple values assigned to attributes and remarks. I initially thought of aggregating them within an array and managing them through their respective IDs.
@jelhan
My approach was to enable the creation and deletion of relationships, identified by their unique IDs, along with their associated fields.
If we consider using a linked object, the JSON:API implementation might appear as follows:
{
"data": {
"type": "buildingCharacteristic",
"id": "123",
"attributes": {
"value": "5",
"remark": "new desks will be added in the future"
},
"relationships": {
"building": {
"links": {
// building
"self": "/buildingCharacteristic/123/relationships/building",
"related": "/buildingCharacteristic/123/building"
}
},
"attribute": {
"links": {
// characteristic for number_desks
"self": "/buildingCharacteristic/123/relationships/characteristic",
"related": "/buildingCharacteristic/123/characteristic"
}
}
}
},
"links": {
"self": "buildingCharacteristic/123"
}
}
How should we handle the endpoints in this scenario?
When we create the linked object, the relationship with the building will automatically be established. Consequently, attempting to add the relationship through the building endpoint would be invalid. Furthermore, deleting the relationship via the building endpoint would result in the deletion of the linked object, just as if the linked object were deleted directly.
I would recommend only allowing modifications of the relationship by creating and deleting the intermediate resource (buildingCharacteristic in this case). You don’t get any benefit if supporting updating the relationships from building and characteristc to that intermediate resource. Just more complexity and side-effects to manage (and inform the client about).