Using a sub-resource or not?
Asked Answered
B

3

6

Let's take the following example:

We want to expose company and employee information from a RESTful API.

Company data should be quite simply:

GET api/v1/companies
GET api/v1/companies/{id}

Employees BELONG to a company, but we still want to retrieve them individually as well, so which solution is best:

Solution 1: Using sub-resources

Get all employees for a company:

GET api/v1/companies/{companyId}/employees

Get a specific employee:

GET api/v1/companies/{companyId}/employees/{employeeId}

Solution 2: Using an independent resources

Get all employees for a company:

GET api/v1/employees?companyId={companyId}

Get a specific employee:

GET api/v1/employees/{employeeId}

Both options seem to have their pros and cons.

  • With sub-resources, I may not always have the CompanyId on hand when wanting to retrieve an individual employee.

  • With an independent resource, getting all employees for a company should use the sub-resource approach if we want to be RESTful.

Otherwise, we could use a mix, but this lacks consistency:

Get all employees for a company:

GET api/v1/companies/{companyId}/employees

Get a specific employee:

GET api/v1/employees/{employeeId}

What is the best approach to take in such a situation if we want to stay true to RESTful standards?

Billowy answered 7/11, 2014 at 6:55 Comment(0)
N
3

For me this sounds like the common many-to-many relationship problem for RESTful services. (see How to handle many-to-many relationships in a RESTful API?)

Your first solution seems good at first but you will have problems whenever you want to access the relation itself.

Instead of returning the employee with the following GET request you should return the relation.

GET api/v1/companies/{companyId}/employees/{employeeId}

If the relation can be identified by 2 keys this solutions seems to be fine. But what happens if the relation is identified by 3+ id's? The URI becomes rather long.

GET api/v1/companies/{companyId}/employees/{employeeId}/categories/{categoryId}

In this case I would come up with a separate resource for the relation:

GET api/v1/company-employees/{id}

The returned model in JSON would look like this:

{
   "id": 1 <- the id of the relation
   "company": {
      "id": 2
   },
   "employee": {
      "id": 3
   },
   "category": {
      "id": 4
   }
}
Norvell answered 7/11, 2014 at 12:23 Comment(0)
V
1

I think it would be okay to provide both. If you want the client to browse through the list of companies first, then select a company and then get the list of all employees, the first approach is necessary. If, may be in addition, you want the client to be able to filter employees by name or age, but without knowing the company identifier, you must provide the second approach as well. It depends on what you want the client to do. In my opinion, it would not be necessary to provide the second approach, if clients can only filter employees by company identifier.

Vaginectomy answered 7/11, 2014 at 7:50 Comment(0)
O
1

I would go for the first approach and providing some links to retrieve the subordinate resource.

If I take the example of a new employee that you may add in a company. It seems to be difficult, for the client with the second approach to make a POST on your collections. Why ? Because he has to know the company id that is "somewhere else". With the first approach, as you followed a path, you already know this information (the companyId)... so it's easier for the client to add a new employee.

Back to your example, the main benefit of the second approach is, if your client want something like "the amount of employees in a city", where you don't care about the notion of company. But it seems that you need the notion of company, so I would go for the first.

Also, very related to this question: RESTful design: when to use sub-resources?

Occur answered 7/11, 2014 at 11:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.