How to pass an array of objects through a query string according to REST?

Viewed 1423

What is the best practice to pass an array of objects throught query string in REST style?

For example, the array:

examples[] = [
  { 
    name: "foo",
    value: "1"
  },
  {
    name: "bar",
    value: "2"
  }
]

I thought about it:
/items?examples[0][name]=foo&examples[0][value]=1&examples[1}[name]=bar&examples[1][value]=2
Are there other ways to do this?

Upd:
I need readable URL to show it to the user in the address field. It should display state of some filters in the table, I'm not sending it to the backend.

3 Answers

You shouldn't take care about how pass data for a backend, Angular do it for you.

About your example, you probably want to update or save several item. So it's not into the url that you will pass your data but into the Request Body :

this.httpService.post(yourUrl, examples, yourHttpOptions).subscribe( (response) => {
  // you manage your response data
});

REST does not care how you encode information into your identifiers. You can use any scheme you want, so long as it is consistent with the production rules defined by RFC 3986.

REST cares a little bit about how you share information about creating URI, in the sense that that information should be shared in some readily standardizable form, like an HTML form, or a URI Template.

We don't, to my knowledge, have a "readily standardizable form" that describes how to transform a json array to a query string.

But... REST does allow code on demand; embedding, for example, a bunch of java script into a resource where that javascript knows how to encode the json into the URI... that is in bounds, so long as you have the code on demand itself referenced in a readily standardizable way (like we have with HTML and script tags).

In practice? urlencode the json representation and put it onto the query string directly. That will get you through until you start to discover the real requirements that your URI design needs to support (requirements like: operators needing to be able to understand the access logs).

Since you're parsing this manually in JS, you could keep the structure you have and just write a parsing function

var items = {}; 

location.search.split("?")[1].split("&").map((q) => {
  var [token, value] = q.split("="),
      [idx, key] = /\[([0-9+])\]\[(\w+)\]/g.exec(token).slice(1, 3);
  
  if (!items[idx]){
    items[idx] = {};
  } 
  
  items[idx][key] = value;
})

This will yield you something with a structure like

{
  "0": {
    "key1": "data"
    "key2": "data:
  },
  "1": {
    "key1": "data"
    "key2": "data"
  }
}

If you need it to end up an array, it would be pretty easy to convert, but keeping it as an object with numeric strings for keys will prevent an error if it's not sequential.

Also, note there's no error checking or anything here, so if you're going to have query string params that aren't in that format, you'll want to test for that and handle them differently.

Related