59

I need to create url for get which is going to accept array, how in node.js/express extract array from request ? I need to pass array with names which parametes I need to back from Person

model.

/api/person # here I need to pass which fields I want to see but to be generic.

10 Answers 10

81

One option is using a JSON format.

http://server/url?array=["foo","bar"]

Server side

var arr = JSON.parse(req.query.array);

Or your own format

http://server/url?array=foo,bar

Server side

var arr = req.query.array.split(',');
Sign up to request clarification or add additional context in comments.

6 Comments

A word of warning to others, that JSON.parse will be fragile and needs a try/catch in the event of invalid JSON being sent...
There are risks when your content contain ',' .
Indeed, it might not work for all cases. Mine was [1,[2,3,[4],5],6]
The closest are Array.from(arr) and Object.values(arr) also don't work for this case
This shouldn't be the top answer since express supports turning repeated values into an array. You shouldn't be writing one off implementations with JSON parse
|
59

Express exposes the query parameter as an array when it is repeated more than once in the request URL:

app.get('/', function(req, res, next) {
   console.log(req.query.a)
   res.send(200)
}

GET /?a=x&a=y&a=z:
// query.a is ['x', 'y', 'z']

Same applies for req.body in other methods.

3 Comments

GET /?a=x&a=y&a=z:
this seems to be the most resilient answer , but can you provide some link from the official doc which shows this as a baked in feature and not a bug? from what i know, other servers frameworks would overwrite the value if the query param gets repeated
@anshsachdeva I was wondering the same, made some research and was going to comment here, but it become way too long for a comment. So, I posted a new answer: stackoverflow.com/a/76814912/287976 Summing up: it is documented for querystring parser, but not for qs, although it does work on qs. This investigation didn't give me all confidence on using repeated parameters (with caveats), but gave me enough confidence on this method.
47

You can encode an array in percent encoding just "overwriting" a field, formally concatenating the values.

app.get('/test', function(req,res){
    console.log(req.query.array);
    res.send(200);
});




localhost:3000/test?array=a&array=b&array=c

This query will print ['a','b','c'].

Comments

31

Using next code:

app.use('/', (req, res) => {
    console.log(req.query, typeof req.query.foo, Array.isArray(req.query.foo));
    res.send('done');
});

On backend, you have two standard approaches. For next requests:

  1. /?foo=1&foo=2
  2. /?foo[]=1&foo[]=2

your NodeJS backend will receive next query object:

  1. { foo: [ '1', '2' ] } 'object' true
  2. { foo: [ '1', '2' ] } 'object' true

So, you can choose the way you want to. My recommendation is the second one, why? If you're expect an array and you just pass a single value, then option one will interpret it as a regular value (string) and no an array.

[I said we have two standards and is not ok, there is no standard for arrays in urls, these are two common ways that exist. Each web server does it in it's own way like Apache, JBoss, Nginx, etc]

5 Comments

Are you sure option 2 behaves as an array with one value in Node? I have found it reverts to a single value. Also I have found the variable name comes in with the braces like 'foo[]'. Looking at the spec here nodejs.org/api/querystring.html it seems it just ignores the braces and will array-ify any parameter with multiple values. I'd like what you say to to be true - it's annoying otherwise!
Hi @scipilot, I tested it again using last express js version 4.16.4 and the result is the same as point 2: { foo: [ '1', '2' ] } 'object' true what means req.query is an object with a key named "foo" (in this example) which has Array type, containing the values '1' and '2'. You can test it by yourself and see the result, here is the curl I used: curl 'localhost:8000/jose?foo[]=1&foo[]=2' -g
Just to be sure, I was only questioning if option 2 still produces an array when you only provide ONE value. i.e. the url would be just /?foo[]=1 which arrives as a variable named "foo[]" with a value of 1. I see what you describe with two values, but that's not how you sell the second option in your penultimate paragraph. If it's different for you perhaps it's modified by middleware. Anyway - I'll test it again too.
Ah, now I see your point, yes, the result is the same (an object containing an array). This is the result { foo: [ '1' ] } 'object' true for next request: curl 'localhost:8000/jose?foo[]=1'
OK thanks for clarifying. If I get time, I'll try more experiments with removing middleware and the like. I wish mine worked like yours - simpler!
8

If you want to pass an array from url parameters, you need to follow the bellow example:

Url example:

https://website.com/example?myarray[]=136129&myarray[]=137794&myarray[]=137792

To retrieve it from express:

console.log(req.query.myarray)
[ '136129', '137794', '137792' ]

Comments

4

Express allows you to use either Node's built-in querystring module or the qs library for parsing query strings, as noted in the documentation. Let’s explore how we can send an array of values to them via query parameters.


Handling Repeated Query Parameters

You can repeat query parameters in the query string to produce an array on the server side. Both querystring and qs handle this use case effectively:

> querystring.parse('a=b&a=c')
[Object: null prototype] { a: [ 'b', 'c' ] }
> qs.parse('a=b&a=c')
{ a: [ 'b', 'c' ] }

Drawback

With this approach, you may end up with either an array (if the parameter is repeated) or a string (if the parameter appears only once):

> querystring.parse('a=b&a=c')
[Object: null prototype] { a: [ 'b', 'c' ] }
> querystring.parse('a=b')
[Object: null prototype] { a: 'b' }

Using Explicit qs Syntax for Arrays

The qs parser provides more explicit and reliable notations to ensure the result is always an array, even if there's only one value. These options include:

  • Bracket Notation
    > qs.parse('a[]=b&a[]=c')
    { a: [ 'b', 'c' ] }
    
  • Index Notation
    > qs.parse('a[1]=c&a[0]=b')
    { a: [ 'b', 'c' ] }
    

These notations are particularly useful because they guarantee an array is returned, even for a single value:

> qs.parse('a[]=b')
{ a: [ 'b' ] }
> qs.parse('a=b')
{ a: 'b' }

Drawback

These notations do not work with querystring:

> querystring.parse('a[]=b')
[Object: null prototype] { 'a[]': 'b' }

Summary

  • Repeated Parameters: Work with both parsers but return an array only when the parameter is repeated.
  • qs Array Syntax: Guarantees an array but doesn’t work with querystring.

Documentation Insights

The official documentation is not very explicit about arrays of values in query strings. That is why we relied mostly in experimentation here. That said, it provides some relevant information here and there.

The Node.js querystring documentation includes an example showing repeated parameters result in an array:

For example, the query string 'foo=bar&abc=xyz&abc=123' is parsed into:

{
  foo: 'bar',
  abc: ['xyz', '123']
}

The qs documentation doesn’t explicitly mention repeated parameters for parsing but does confirm their behavior during stringification. In practice, repeated parameters work as expected:

> qs.parse('a=b&a=c')
{ a: [ 'b', 'c' ] }

Comments

2

Express has a tool to check if your path will match the route you are creating : Express.js route tester.

As Jose Mato says you have to decide how to structure your url:

  1. ?foo=1&foo=2
  2. ?foo[]=1&foo[]=2

The http request should look like this, if you chose method 1:

http://baseurl/api/?foo=1&foo=2

Your route should have this logic:

app.get('/api/:person', (req, res) => {
    /*This will create an object that you can iterate over.*/
    for (let foo of req.params.foo) {
      /*Do some logic here*/
    }
});

Comments

0

Here use this, '%2C' is the HTML encoding character for a comma.

jsonToQueryString: function (data) {
   return Object.keys(data).map((key) => {
        if (Array.isArray(data[key])) {
            return encodeURIComponent(`${key}=${data[key].map((item) => item).join('%2C')}`);
        }
        return encodeURIComponent(`${key}=${data[key]}`);
    }).join('&');
}

To access the query params

const names = decodeURIComponent(req.query.query_param_name);
const resultSplit = names.split(',');

Comments

0

Theres a problem when the array param contains only one value, because then it behaves like a simple string. Or when it doesn't contain any value.

Eg.:

  • ?arrayParam=5
  • ?
  • ?arrayParam=5&arrayParam=6

Here's a function that always extracts the param with the given name, as an array:

export function extractArrQueryParams(
  req: express.Request,
  paramName: string
) {
  let param = req.query[paramName];
  let returnArray = [];

  if (Array.isArray(param)) {
    for (let e of param) {
      returnArray.push(e);
    }
  } else {
    if (param) {
      returnArray.push(param);
    }
  }

  return returnArray;
}

Comments

-1

You can pass array elements separated by slashes - GET /api/person/foo/bar/...

Define your route as '/api/person/(:arr)*'

req.params.arr will have the first parameter. req.params[0] will have the rest as string. You split and create an array with these two.

app.get('/api/person/(:arr)*', function(req, res) {
        var params = [req.params.arr].concat(req.params[0].split('/').slice(1));
        ...
});

GET /api/person/foo
params = ["foo"]

GET /api/person/foo/bar
params = ["foo", "bar"]

...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.