Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Providing an array as a param isn't working as expected. #604

Closed
marksauter opened this issue Dec 16, 2016 · 9 comments
Closed

Providing an array as a param isn't working as expected. #604

marksauter opened this issue Dec 16, 2016 · 9 comments

Comments

@marksauter
Copy link

Hi,
I attempting to use the USDA Food Composition Database's API to access nutritional information. I want to put in the following get request using axios config.params object:

https://api.nal.usda.gov/ndb/nutrients/?format=json&api_key=DEMO_KEY&nutrients=205&nutrients=204&nutrients=208&nutrients=269

This is my code for the axios.get request:

axios.get('https://api.nal.usda.gov/ndb/nutrients/', {
    params: {
      format: 'json',
      api_key: 'DEMO_KEY',
      nutrients: [
        205,
        204,
        208,
        269
      ]
    }
  })
  .then(response => console.log(response))
  .catch(error => console.log(error))

But when I get the response, I see that the built url becomes:

https://api.nal.usda.gov/ndb/nutrients/?format=json&api_key=DEMO_KEY&nutrients[]=205&nutrients[]=204&nutrients[]=208&nutrients[]=269

Is this meant to happen? Do other APIs adhere to this format? If so, is there a way to avoid the insertion of '[]' after each 'nutrients' param, so that I may get around this issue for this specific API?

@stsourlidakis
Copy link

According to this test it seems to be the expected behavior.
In order to get around it you could probably use the "paramsSerializer" method.

@marksauter
Copy link
Author

I'll look into that, thank you.

@XidongHuang
Copy link

XidongHuang commented Jul 24, 2017

Hi @stsourlidakis , I am trying to use paramsSerializer for delete method in the front-end, the params can be an array,but I cannot get those params at the back-end.

I set:

//front-end
axios.delete(url, 
        {paramsSerializer: accountsInfo }  //--> paramsSerializer
    ).then(
        (res) => {
            .....
         }
)

My back-end environment is node and koa2, for GET method, I can get params like:

//front-end
axios.delete(`url/${array}`).then(
    (res) => {...}
)

//back-end
handleDelete = async(ctx, next) => {
    let arrayString = ctx.params.array;
}

if I use PUT, PATCH or PATCH, I can get data from body:

//front-end
axios.patch(url, data).then(
     (res) => {...}
)

//back-end
handlePatch = async(ctx, next) => {
    let data = ctx.request.body.data;
    ...
}

So I can get params like above, but not DELETE. I also try qs, however doesn't work neither..
any tips about that?
Thanks

@kmmbvnr
Copy link

kmmbvnr commented Aug 10, 2017

this should helps

var qs = require('qs');

axios.get('api/', {
    'params': {'country': ['PL', 'RU']}
    'paramsSerializer': function(params) {
       return qs.stringify(params, {arrayFormat: 'repeat'})
    },
})

@uniquejava
Copy link

uniquejava commented Mar 20, 2018

Thank you @kmmbvnr , but I'd rather this was a built-in behavior when handling arrays (checkbox values)

PS:
I finally found that this is not a problem, I don't have to use paramsSerializer, as I can easily get the params from backend(Spring Boot) like this:

@GetMapping()
public String search(@RequestParam(name = "country[]") String[] country)

@AndreyPatseiko
Copy link

AndreyPatseiko commented Jul 6, 2018

const transformRequestOptions = params => {
   let options = '';
   for (const key in params) {
   if (typeof params[key] !== 'object' && params[key]) {
     options += `${key}=${params[key]}&`;
   } else if (typeof params[key] === 'object' && params[key] && params[key].length) {
       params[key].forEach(el => {
           options += `${key}=${el}&`;
    });
   }
 }
 return options ? options.slice(0, -1) : options;
};

and

axios.get('api/', {
   params: {'country': ['PL', 'RU']},
   paramsSerializer: params => transformRequestOptions(params) 
})

get options url/country=PL&country=RU

@steniowagner
Copy link

steniowagner commented Sep 11, 2018

Refactoring @AndreyPatseiko 's answer to ES6+ style:

const 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

axios.get('api/', {
   'params': {'country': ['PL', 'RU'], 'nacionality': 'FOO' } // result: country=PL&country=RU&nacionality=FOO

   'paramsSerializer': params => parseParams(params) 
});

BTW, thank you, @AndreyPatseiko! Your answer helped me a lot!

@jorge683
Copy link

jorge683 commented Oct 23, 2019

This is better
axios.get('api/foo...', { params: {arr: [1, 2] + ' ' } )}

@Rambalac
Copy link

@jorge683 that generates incorrect query nutrients=205,204,208,269

@axios axios locked and limited conversation to collaborators May 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants