How to construct a REST API that takes an array of id's for the resources

Rest

Rest Problem Overview


I am building a REST API for my project. The API for getting a given user's INFO is:

api.com/users/[USER-ID]

I would like to also allow the client to pass in a list of user IDs. How can I construct the API so that it is RESTful and takes in a list of user ID's?

Rest Solutions


Solution 1 - Rest

If you are passing all your parameters on the URL, then probably comma separated values would be the best choice. Then you would have an URL template like the following:

api.com/users?id=id1,id2,id3,id4,id5

Solution 2 - Rest

 api.com/users?id=id1,id2,id3,id4,id5
 api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

IMO, above calls does not looks RESTful, however these are quick and efficient workaround (y). But length of the URL is limited by webserver, eg tomcat.

RESTful attempt:

POST http://example.com/api/batchtask

   [
    {
      method : "GET",
      headers : [..],
      url : "/users/id1"
    },
    {
      method : "GET",
      headers : [..],
      url : "/users/id2"
    }
   ]

Server will reply URI of newly created batchtask resource.

201 Created
Location: "http://example.com/api/batchtask/1254"

Now client can fetch batch response or task progress by polling

GET http://example.com/api/batchtask/1254


This is how others attempted to solve this issue:

Solution 3 - Rest

I find another way of doing the same thing by using @PathParam. Here is the code sample.

@GET
@Path("data/xml/{Ids}")
@Produces("application/xml")
public Object getData(@PathParam("zrssIds") String Ids)
{
  System.out.println("zrssIds = " + Ids);
  //Here you need to use String tokenizer to make the array from the string.
}

Call the service by using following url.

http://localhost:8080/MyServices/resources/cm/data/xml/12,13,56,76

where

http://localhost:8080/[War File Name]/[Servlet Mapping]/[Class Path]/data/xml/12,13,56,76

Solution 4 - Rest

As much as I prefer this approach:-

    api.com/users?id=id1,id2,id3,id4,id5

The correct way is

    api.com/users?ids[]=id1&ids[]=id2&ids[]=id3&ids[]=id4&ids[]=id5

or

    api.com/users?ids=id1&ids=id2&ids=id3&ids=id4&ids=id5

This is how rack does it. This is how php does it. This is how node does it as well...

Solution 5 - Rest

There seems to be a few ways to achieve this. I'd like to offer how I solve it:

GET /users/<id>[,id,...]

It does have limitation on the amount of ids that can be specified because of URI-length limits - which I find a good thing as to avoid abuse of the endpoint.

I prefer to use path parameters for IDs and keep querystring params dedicated to filters. It maintains RESTful-ness by ensuring the document responding at the URI can still be considered a resource and could still be cached (although there are some hoops to jump to cache it effectively).

I'm interested in comments in my hunt for the ideal solution to this form :)

Solution 6 - Rest

You can build a Rest API or a restful project using ASP.NET MVC and return data as a JSON. An example controller function would be:

        public JsonpResult GetUsers(string userIds)
        {
           var values = JsonConvert.DeserializeObject<List<int>>(userIds);

            var users = _userRepository.GetAllUsersByIds(userIds);

            var collection = users.Select(user => new { id = user.Id, fullname = user.FirstName +" "+ user.LastName });
            var result = new { users = collection };
            
            return this.Jsonp(result);
        }
        public IQueryable<User> GetAllUsersByIds(List<int> ids)
        {
            return _db.Users.Where(c=> ids.Contains(c.Id));
        }

Then you just call the GetUsers function via a regular AJAX function supplying the array of Ids(in this case I am using jQuery stringify to send the array as string and dematerialize it back in the controller but you can just send the array of ints and receive it as an array of int's in the controller). I've build an entire Restful API using ASP.NET MVC that returns the data as cross domain json and that can be used from any app. That of course if you can use ASP.NET MVC.

function GetUsers()
    {
           var link = '<%= ResolveUrl("~")%>users?callback=?';
           var userIds = [];
            $('#multiselect :selected').each(function (i, selected) {
                userIds[i] = $(selected).val();
            });
           
            $.ajax({
                url: link,
                traditional: true,
                data: { 'userIds': JSON.stringify(userIds) },
                dataType: "jsonp",
                jsonpCallback: "refreshUsers"
            });
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionuclajattView Question on Stackoverflow
Solution 1 - RestFlorin DumitrescuView Answer on Stackoverflow
Solution 2 - RestNileshView Answer on Stackoverflow
Solution 3 - RestShujaView Answer on Stackoverflow
Solution 4 - RestKyristopherView Answer on Stackoverflow
Solution 5 - RestReinsbrainView Answer on Stackoverflow
Solution 6 - RestVasile LaurView Answer on Stackoverflow