How to correctly use axios params with arrays
Asked Answered
C

19

127

How to add indexes to array in query string?

I tried send data like this:

axios.get('/myController/myAction', { params: { storeIds: [1,2,3] })

And I got this url:

http://localhost/api/myController/myAction?storeIds[]=1&storeIds[]=2&storeIds[]=3

So, I should to get this url:

http://localhost/api/myController/myAction?storeIds[0]=1&storeIds[1]=2&storeIds[2]=3

What I should add in my params options to get this url?

Coexist answered 20/4, 2018 at 14:49 Comment(1)
Just out of curiosity - wouldn't the url with [] still work?Twilatwilight
P
164

You can use paramsSerializer and serialize parameters with https://www.npmjs.com/package/qs

axios.get('/myController/myAction', {
  params: {
    storeIds: [1,2,3]
  },
  paramsSerializer: params => {
    return qs.stringify(params)
  }
})
Primordial answered 20/7, 2018 at 14:27 Comment(9)
Helped a lot... Was quite stuck trying to figure out how to build the params myself.Hilliary
Me too :D Thank you so much!Keenan
Even the axios documentation mentions the paramsSerializer just "by the way"Keenan
Note that by doing it, params become a query. So to access it in the back-end, you would have to write req.query instead of req.params. At least that was the case for myself.Iceland
It seems you can also use querystring Node module instead of qs, see #31757256 and github.com/axios/axios/issues/739Repartee
I got it to work using qs.stringify(params, { arrayFormat: "repeat" }) instead of just qs.stringify(params) This answer helped too: https://mcmap.net/q/175915/-multiple-fields-with-same-key-in-query-params-axios-requestCarmichael
qs.stringify(p, {arrayFormat: 'brackets'}) helps meWeigle
Since 1.0.0 axios supports it natively, just set paramsSerializer.indexes to null. ref: github.com/axios/axios#request-configAffirmation
Actually with recent versions, refer to the answer above using indexes property to control this with no need for external libsTracheostomy
F
28

Without having to add more libraries and using ES6 you could write:

axios.get(`/myController/myAction?${[1,2,3].map((n, index) => `storeIds[${index}]=${n}`).join('&')}`);
Fix answered 13/8, 2020 at 19:49 Comment(5)
FYI, Axios is a library. github.com/axios/axiosThesda
Oups! I meant MORE libraries. I corrected the answer, thanks!Fix
I love this answer !. It's pure JS. No library required!.Pede
to get this to work I did instead do .map((n, index) => storeIds[${index}]=${n}).join('&') otherwise since .map returns an array I have to do a join. Otherwise would get an unwanted ',' symbol between each value.Strategy
@PerHyyrynen you are right! I'll correct the answer, thanks!Fix
C
17

Thanks so much the answer from Nicu Criste, for my case, the API requires params like this:

params: {
  f: {
    key: 'abc',
    categories: ['a','b','c']
   },
  per_page: 10
}

Method is GET and this API requires the format is: API?f[key]=abc&f[categories][]=a&f[categories][]=b... So I assigned the paramsSerializer of axios like this:

config.paramsSerializer = p => {
      return qs.stringify(p, {arrayFormat: 'brackets'})
    }
Clabber answered 5/12, 2019 at 12:36 Comment(0)
A
17

This behaviour has been added to axios starting with version 1.0.0. See paramsSerializer.indexes at https://github.com/axios/axios/tree/v1.0.0#request-config

Here's an example using your sample code:

axios.get('/myController/myAction', {
  params: { storeIds: [1,2,3] },
  paramsSerializer: {
    indexes: true, // use brackets with indexes
  }
)

The resulting query params will have indexes inside the brackets:

/myController/myAction?storeIds[0]=1&storeIds[1]=2&storeIds[2]=3

Other paramsSerializer.indexes values are null (no brackets):

axios.get('/myController/myAction', {
  params: { storeIds: [1,2,3] },
  paramsSerializer: {
    indexes: null, // no brackets at all
  }
)
// /myController/myAction?storeIds=1&storeIds=2&storeIds=3

And the default false (brackets without indexes):

axios.get('/myController/myAction', {
  params: { storeIds: [1,2,3] },
  paramsSerializer: {
    indexes: false, // brackets but no indexes
  }
)
// /myController/myAction?storeIds[]=1&storeIds[]=2&storeIds[]=3
Aeneus answered 20/6, 2023 at 17:41 Comment(0)
C
4

In my case, I use ES6 array function. array element make querystring use reduce function. Object array also works.

const storeIds = [1,2,3]
axios.get('some url', {
  params: {
    storeIds: storeIds.reduce((f, s) => `${f},${s}`)
  }
})
Carlocarload answered 21/4, 2020 at 11:29 Comment(1)
Your solution can be written a little shorter storeIds.join(',')Headlock
H
2

There are a lot of good answers here. But I just wanted to share what I ended up using: (works like a charm even with other non-array parameters in your object)

Here is my params object:

params: {
    city: '335471',
    size: 4,
    page: 1,
    type: [1, 2, 3, 4, 5, 6],
}

This is the axios get method:

$axios.get('/some/api/endpoint/', {
    params,
    paramsSerializer: (params) => parseParams(params),
})
function parseParams(params) {
  const keys = Object.keys(params)
  let options = ''

  keys.forEach((key) => {
    const isParamTypeObject = typeof params[key] === 'object'
    const isParamTypeArray = isParamTypeObject && params[key].length >= 0

    if (!isParamTypeObject) {
      options += `${key}=${params[key]}&`
    }

    if (isParamTypeObject && isParamTypeArray) {
      params[key].forEach((element) => {
        options += `${key}=${element}&`
      })
    }
  })

  return options ? options.slice(0, -1) : options
}

And finally, using this method you will send this request:

https://yourwebsite.com/api/some/api/endpoint/?city=335471&size=4&page=1&type=1&type=2&type=3&type=4&type=5&type=6

source: https://github.com/axios/axios/issues/604#issuecomment-420135579

Heraldry answered 24/5, 2023 at 15:56 Comment(0)
L
1

In my case, I am using someting like this

const params = array.map((v)=>{
            return `p=${v}&`
        })

Only concat params.join('') to the URL where you get data:

`url_to_get?${params.join('')`

In my back-end in ASP.net I receive this

[FromUri] string [] p
Linkage answered 2/6, 2020 at 17:11 Comment(0)
S
1

I rewrote the existing paramSerializer shipped in axios. The following snippet does the same serialization while putting indices between square brackets. I tried qs but it is not compatible with my python connexion backend (for JSON string parameters).

const rcg = axios.create({
    baseURL: `${url}/api`,
    paramsSerializer: params => {
        const parts = [];

        const encode = val => {
            return encodeURIComponent(val).replace(/%3A/gi, ':')
                .replace(/%24/g, '$')
                .replace(/%2C/gi, ',')
                .replace(/%20/g, '+')
                .replace(/%5B/gi, '[')
                .replace(/%5D/gi, ']');
        }

        const convertPart = (key, val) => {
            if (val instanceof Date)
                val = val.toISOString()
            else if (val instanceof Object)
                val = JSON.stringify(val)

            parts.push(encode(key) + '=' + encode(val));
        }

        Object.entries(params).forEach(([key, val]) => {
            if (val === null || typeof val === 'undefined')
                return

            if (Array.isArray(val))
                val.forEach((v, i) => convertPart(`${key}[${i}]`, v))
            else
                convertPart(key, val)
        })

        return parts.join('&')
    }
});
Semibreve answered 8/4, 2021 at 7:32 Comment(0)
P
1

This answer is inspired by @Nicu Criste's answer.

But might be not related to the posted question.

The following code was used to generate the query params with repetitive keys which had been supplied with an object array.

Note: If you are a developer with bundlephobia, use the following approach with care: as with UrlSearchParams support varies on different browsers and platforms.

const queryParams = [{key1: "value1"}, {key2: "value2"}]

axios.get('/myController/myAction', {
  params: queryParams,
  paramsSerializer: params => {
    return params.map((keyValuePair) => new URLSearchParams(keyValuePair)).join("&")
  }
})

// request -> /myController/myAction?key1=value1&key2=value2
Peregrination answered 7/4, 2022 at 2:18 Comment(0)
S
1

you can create a function as parseParams that can send the params to this function and serialize it.

axios.get('/myController/myAction', {
  params: {
    storeIds: [1,2,3]
  },
 paramsSerializer: params => parseParams(params)
})

parseParams function is;

export const parseParams = (params) => {
  let options = '';

  for (const [key, value] of Object.entries(params)) {
    if (Array.isArray(value)) {
      for (const element of value) {
        options += `${key}=${element}&`;
      }
    } else {
      options += `${key}=${value}&`;
    }
  }

  return options.slice(0, -1);
};
Susa answered 4/4, 2023 at 13:10 Comment(0)
G
0

I got using "paramSerializer" a bit confuse. Before looking for the "right way" to use axios with array querystring on Google, I did following and got working:

var options = {};
var params = {};
for(var x=0;x<Products.length;x++){
   params[`VariableName[${x}]`] = Products[x].Id;
}
options.params = params;

axios.get(`https://someUrl/`, options)...

It is going to create querystring parameters like:

VariableName[0]=XPTO,VariableName[1]=XPTO2

which the most webservers expected as array format

Gosnell answered 20/5, 2021 at 19:35 Comment(0)
G
0

I know that this approach is not very good and I don't know the downsides it may have, but i tried this and it worked:

before making the request, prepare the params:

  let params = '?';

  for (let i = 0; i < YOUR_ARRAY.length; i++) {  // In this case YOUR_ARRAY == [1, 2, 3]
    params += `storeIds=${YOUR_ARRAY[i]}`;  // storeIds is your PARAM_NAME
    if (i !== YOUR_ARRAY.length - 1) params += '&';
  }

And then make the request like so:

axios.get('/myController/myAction' + params)
Glauconite answered 6/2, 2022 at 10:9 Comment(0)
W
0

In React I needed to use axios with a params in array. This was query param:

"fields[0]=username&fields[1]=id&populate[photo][fields][0]=url&populate[job][fields][1]=Job"

to send with axios, for that I installed by CLI

npm install qs Read more about qs

and declared

const qs = require('qs');

after
const query = qs.stringify({
fields: ['username', 'id'],
populate: {
photo: {
fields: ['url']
},
job: {
fields: ['Job']
}
}
}, {
encodeValuesOnly: true
});

and finally I called the axios like this:
axios.create({
baseURL: "http://localhost:1337/api/",
}).get(`/users?${query}`) // this parameter show all data
.then((response) => console.log(response.data))
.catch((err) => {
setError(err);
});

Writing answered 13/7, 2022 at 19:45 Comment(0)
S
0

Basically, reading from docs https://axios-http.com/docs/req_config
paramsSerializer is an optional function, which we should use if the default serialization of params done by axios is not as expected.

We can use serialization libraries (which I feel is best approach) to serialize in the params in the paramsSerializer function as per our needs.
Let's see an example.Suppose params is like ...

{
      params: {
        delay: 1,
        ar:[1,2,3]
      }
}

then you will get queryString like this ?delay=1&ar[]=1&ar[]=2&ar[]=3 when you make the request, but you might want like this ?delay=1&ar[0]=1&ar[1]=2&ar[2]=3

so in order to get query string as per our format. we can use qs https://www.npmjs.com/search?q=qs library
and serialize our params in the paramsSerializer function as below

{
      method: "GET",
      params: {
        delay: 1,
        ar:[1,2,3]
      },
      paramsSerializer: (params) => {
        return qs.stringify(params,{
          encodeValuesOnly: true
          });
      }
},
Senility answered 25/11, 2022 at 3:32 Comment(0)
A
0

I had the issue that I wanted axios to omit brackets altogether. So I ended up with setting the paramsSerializer.indexes field to null. You can have the indices set as you want though by setting indexes to true.

axiosInstance.defaults.paramsSerializer = {
 
  // e.g. instead of
  // storeIds[]=1&storeIds[]=2&storeIds[]=3

  // you get
  // storeIds[0]=1&storeIds[1]=2&storeIds[2]=3

  // with
  indexes: true
};

It can also be set per request as it is part of the AxiosRequestConfig interface:

axios.get(
  '/myController/myAction',
  { 
    params: { 
      storeIds: [1,2,3] 
    }, 
    paramsSerializer: {
 
      indexes: true
    }
  }
)
Anticipation answered 21/3, 2023 at 12:52 Comment(0)
I
0

I am working with nestjs and had to pass array in query, but it didnt successeded, I tried qs and paramsSerialization, but it didnt work. So I just join array with "," on one server and split it on another with ",". Fortunately, nestjs has @Transform, so it is easy to do.

array: array.join(',')

Code in dto:

@IsArray()
@IsString({ each: true })
@IsOptional()
@Transform(({ value }) => value.split(','))
  array: string[]; 
Infidelity answered 17/4 at 13:52 Comment(0)
B
-1

This work it for me:

axios.get("/financeiro/listar",{
        params: {
          periodo: this.filtro.periodo + "",
          mostrarApagados: this.filtro.mostrarApagados,
          mostrarPagos: this.filtro.mostrarPagos,
          categoria: this.filtro.categoria,
          conta: this.filtro.conta
        }
      })

enter image description here

Brutality answered 1/5, 2021 at 1:50 Comment(0)
I
-3

This was better for me:

axios.get('/myController/myAction', {
params: { storeIds: [1,2,3] + ''}

})

Imprecise answered 23/10, 2019 at 14:53 Comment(11)
That will not give the desired result.Irrelative
It does not give exactly the expected result, but it worksImprecise
It does something but you can't say it works if it doesn't do what the OP needs it to do.Irrelative
Also please note that a solution that does do what is needed was found over a year ago and currently has a score of 18.Irrelative
It is true. But it's always good to try to offer some better solution.Imprecise
But it isn't better. It's a comma-separated string, which standard form data parsers will not separate for you, and which won't handle data with commas in this (this particular example only has digits so that isn't a problem in this specific case).Irrelative
That's why I clarified that it was the best in my case. That worked for me, I think others could do something similar according to needImprecise
I tried both solutions and this one is the only one that works for me. I use ids, It creates in the request the property params: id1,id2,id3 and it works!!!Lanneret
If you have full control of the server side API you are communicating with: then this is a VERY neat/terse way to get your required data up (from the client) using axios and a get request. It does not create a query string as the OP asked for, but it IS very simple, neat and efficient way to do some of what the OP was asking for i.e. for a Get request, using Axios: how do I put my "array in query string".Cuthburt
N.B. produces a url like : localhost/api/myController/myAction?storeIds=1,2,3Cuthburt
@Irrelative is right that most server side frameworks by default will not parse this correctly, but N.B. we are talking GET request here. i.e. may well not be "form data" (usually POST requests), and if you care about clarity and the number of bytes you're pushing up the wire this might be a good solution when coupled with some customisation on the server.Cuthburt
C
-3

In my case, there was already jQuery implemented into my codebase. So I just used the predefined method.

jQuery.param(Object)
Chalcidice answered 3/11, 2019 at 15:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.