Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POST a list of items using REST

Tags:

rest

post

I'm looking for a convention on how to serialize my data when I have a (long) list of items that I want to POST to the server.

For example, if I have a resource /users and I wanted to POST a new one to it, I'd http-encode the fields for the new user and put it in the request body like this: name=foo&age=20

But if I have a list of users, like this [{ name: 'foo', age: 20 }, { name: 'bar', age: 10 }], is there a conventional way of POSTing this?

I'm thinking name[0]=foo&age[0]=20&name[1]=bar&age[1]=10 but I can't find anything to back it up. What do web servers usually accept/expect?

like image 431
Jakob Avatar asked Nov 19 '11 14:11

Jakob


People also ask

How do I use REST API in SharePoint?

To use the REST capabilities that are built into SharePoint, you construct a RESTful HTTP request by using the OData standard, which corresponds to the client object model API you want to use. The client. svc web service handles the HTTP request and serves the appropriate response in either Atom or JSON format.


2 Answers

Quick question which may change my answer: Are you POSTing directly from an HTML form or are you expecting something more sophisticated (e.g. javascript processsing, or not even a web-based client)

If you have a sophisticated enough client, you could just construct a JSON string and POST with a content type of application/json. Then whatever resource is processing the POST could use any number of json libraries to read the posted string and process as is.

Further Rambling:

What framework/languages are you using to construct your REST service? Do they have built-in functionality/conventions to help you?

For example if you're using JAX-RS to build your service, there is a built in annotation @FormParam which can be used to process posted forms... for example: if you posted the following with a content type of application/x-www-form-urlencoded: name=foo&age=20&name=bar&age=10

You could retrieve parallel lists on the service side via:

@POST
@Consumes("application/x-www-form-urlencoded")
public void createUsers(@FormParam("name") List<String> name, @FormParam("age") List<String> age) {
    // Store your users
}

But you would then have to deal with the question of what if one list is shorter/longer than the other, how do you resolve that? What happens if a new field is required or optional to create a list of users? (But as I mentioned initially, a JSON array of JSON objects would solve that issue... there are a number of libraries out there that support automagic JSON deserialization in JAX-RS or there is also the option of creating your own MessageBodyReader.

(Disclaimer on the next section: I don't know rails, my experience is more in the Java services world... I'm basing this on this guide). It looks like Rails has a convention of name[]=foo&name[]=bar to process posted data into arrays automagically, and a similar convention to populate structure like user[name]=foo&user[age]=20... Perhaps if you are on rails there is some way to use/abuse both of these features to get the desired result?

Other REST frameworks and languages may have their own conventions and functionality :)

like image 140
Charlie Avatar answered Nov 17 '22 05:11

Charlie


Rails serializes forms on a format not unlike what you suggest. If you have a nested model it encodes it like this:

name=theo&company[name]=acme

(the equivalent JSON would be {"name": "theo", "company": {"name": "acme"}})

I can't say that I've seen a Rails application sending arrays, but there's no reason why it wouldn't work (worst case you would end up with a hash with string keys).

PHP has another convention, if you want to send an array you do

names[]=alice&names[]=bob&names[]=steve

But I don't know how you do nested objects that way.

The HTTP spec, or if it's the URI spec, not sure which atm, actually specifies that if you pass the same argument multiple times you get array of values (instead of the last-wins behaviour of most application frameworks). You can see this in the API docs for Jetty, for example: http://api.dpml.net/org/mortbay/jetty/6.1.5/org/mortbay/jetty/Request.html#getParameterValues(java.lang.String)

However, most of this applies to GET requests, not necessarily POST (but perhaps application/x-url-encoded should adhere to the same standards as GET).

In short, I don't think there is a standard for doing this, POST bodies are a bit of a wild west territory. I think, however, that either you should go with JSON, because it's made to describe structures, and application/x-url-encoded is not, or you should try to represent the structure of your data better, something like:

users[0][name]=foo&users[0][age]=20&users[1][name]=bar&users[1][age]=10

That has some kind of chance of actually being interpretable by a Rails app out of the box, for example.

like image 22
Theo Avatar answered Nov 17 '22 05:11

Theo