Home > front end >  What is the correct REST representation to query multiple attributes
What is the correct REST representation to query multiple attributes

Time:05-10

There is an entity,

class Employee{
  int id;
  String name;
  String phoneNumber;
}

What is the correct REST-ful way of querying the following 4 scenarios:

  1. List of all employees
  2. Employee with a given ID
  3. Employee with a given ID and Name
  4. Employee with a given ID and Name and PhoneNumber

starting two are pretty straight forward:

1. /employee
2. /employee/{employee-id}

however, now that we want to filter an entity on the basis of multiple attributes, the best solution I could think of was:

3. /employee/{employee-id}?name=abc
4. /employee/{employee-id}?name=abc&phoneNumber=123

Are there any better ways of doing this? Some people suggested solutions like:

3. /employee/{employee-id}/{name}
4. /employee/{employee-id}/{name}/{phoneNumber}

however, I feel the above violates the RESTful way of representing.

CodePudding user response:

In REST API, you have to separate collections and specific resources. I would be explicit with that by specifying a collection in plural, and resource in singular. Hence a specific resource in a collection can be fetched by /{collectionName}/{id} and if you want to query on attributes, use /{collectionName}?attribute1=qwe&attribute2=asd

So... I would rather structure it like this:

/employees                             # the entire collection of employees
/employees/{id}                        # a specific employee by id. No need to have any query params since we fetch an employee by its primary key.
/employees?name=abc&phoneNumber=123    # query the collection of employees for the ones having name=abc and phoneNumber=123

CodePudding user response:

Searching for an employee by ID and Name (and PhoneNumber) is a bit ambiguous.

Normally, looking up an employee by ID is not considered a search, but a reference to an existing resource (a GET). If it fails, an HTTP 404 NOT FOUND should be returned.

Searching by multiple attributes could typically be a POST:

POST /employees/search/
{
    "Name": "Hasan",
    "PhoneNumber", "0612345678"
}

The reasoning is that you are 'creating' a search query here, with the given attributes, hence the POST. If the search yields no results, an HTTP 204 NO CONTENT should be returned.

Mixing lookup by ID and search by (multiple) attributes raises some questions:

  • Are only results returned that match all the attributes? Or results that match any of them?
  • Should matching be literal, or use some other syntax, or substring matching as default behavior? And how about the ID attribute?
  • Would you expect an error if there are no results? Or an empty collection?
  • Which HTTP response code will you return in this case?

Using a GET to look up and POST to search is in line with the REST mindset. If you POST a search you are creating a resource which has a unique ID you can store. You can later retrieve this query, for example to select the next page of results.

EDIT: Maybe (probably) I should not have brought up the GET/POST debate. There are strong arguments for/against both of them, so you should choose what suits you best in your specific case. See for example this discussion.

What it boils down to for me, is that I don't understand your requirement. What's the meaning of this:

/employee/{employee-id}?name=abc&phoneNumber=123

Can there be multiple employees with the same employee-id?

CodePudding user response:

Using a JSON string as a parameter, we can create a single API. This approach has the benefit of not requiring multiple parameters in the API parameters, and it would be easy to add options to the filter in the future.

@Getter
@Setter
class EmployeeDTO {
  int id;
  String name;
  String phoneNumber;
}

The following is an example of APIs

@GetMapping("/employee")
public String getEmployee(@RequestParam(value = "searchParams") String employee)
        throws JsonMappingException, JsonProcessingException {
    EmployeeDTO employeeDTO = new ObjectMapper().readValue(employee, EmployeeDTO.class);
    // add your code
}

Frontend data should be passed as a JSON string

localhost:8080/employee?searchParams={"id":1,"name":"Abc","phoneNumber": 12345}

Required dependency

<dependencies>
   <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
   </dependency>
</dependencies>

In case of the error "Invalid character found in the request target.", add the property below to the application.property file.

server.tomcat.relaxed-query-chars=|,{,},[,]
  • Related