Home > Software engineering >  RESTful API with associations best practice
RESTful API with associations best practice

Time:10-21

We are implementing a RESTful API and we have POST request that looks like this /v1/systems/{systemId}/subsystems and the body looks like this {"id": 0, "systemId": 0, "name": "string"}. Is this a duplication of the variables? It is good practice to have it like this?

CodePudding user response:

The URI as a whole is an identifier for the resource not just the last part. Whether the URI itself follows some structural design or not is also dependent on your design decisions. On its own a URI like .../systems/{systemId}/subsystems does not necessarily state that it is part of a systems collection with a parent resource identified by the respective systemId. This only "evolves" if a client naturally explores URIs that in total span a tree where this relationship is build. Though, such relations are usually expressed with link relations like up to reference the parent resource and item for a specific item in a collection, subsection for a sub-part of a collection resource an so forth. See Iana's link relation registry whether there are link relations available that fits your need. If none of the available link-relations fit your needs you can either register new ones with Iana or make use of Web linking relation extensions where you can define private relations in your own namespace.

In regards to adding the systemId in the body when you utilize a URI structure where the systemId is already used in the path to identify the parent resource, that information is then clearly redundant. But whether you want to include it still in the payload is your design choice. There is nothing wrong to include it or leave it out.

Unfortunately the information on the subsystems resource is rather limited. The current payload given could potentially be reduced to the name itself as the systemId is given in the URI and the id of the subsystem resource may be auto-generated and not be defined by the client. As such, the payload would reduce to a single name. Here you could also avoid the creation of the subresource alltogether and model the name of the subsystem within the system entry itself by designing it as array of names. Here, instead of a sub-resource creation you could simply provide an update method for the system resource (via Patch) to add the name to that array. But again, it is your design. Whatever works for you is fine here.

As a rule of thumb whether to include such information in the payload or not you can take the Web as example. I.e. if the ID should be part of the representation to present to the final user, put it in. If not, leave it out. Think of a product which you want to render on a page. Sometimes it may be helpful if the respective productId is present if you want to give the customer a unique way of addressing that particular product in case of reclamations or questions. As resource identifiers however shouldn't change if possible it might be more benefitial to expose a UUID as internal product identifier and carry the product identifier customers should use in an other field with it. A customer of us once had a merger and in that merger they basically joined products from two companies all with different identifiers in their databases. As a consequence they had to modify a lot of resource URIs eventhough the products (in their real form) didn't change at all. As such, certain customers where all of a sudden unable to access previously bookmarked product descriptions and so forth as no redirect were introduced unfortunately. This for sure is an extreme and rare situation, though it may occur, and if you'd used a design that supports such a change by design the impact on the whole system would have been notably less dramatic.

So, long story short, it depends on your design whether the systemId is redundant information or whether you want to add that information to the payload or not or even avoid the subresource alltogether and instead carry the name within a listing of the parent system itself. There is neither a right nor wrong answer here.

CodePudding user response:

Normally, one doesn't POST to create a resource to a URL that points to a single resource. Your URL looks more correct for a GET, PUT or DELETE.

Without knowing your exact requirements, one could do:

POST body {"systemId": 0, "name": "string"} to /v1/systems or /v1/subsystems

The response could contain the created subsystem along with the new id.

  • Related