unjs/ufo

Query param array of object is not stringified

Kapcash opened this issue ยท 3 comments

When using withQuery, arrays of objects are not serialized properly and becomes [object+Object].
I'd expect it to be at least stringify with JSON.stringify.

Current result:

withQuery('http://localhost:3000', { filters: [{ id: 1}, { name: 'ufo' }] })
// 'http://localhost:3000?filters=[object+Object]&filters=[object+Object]'

Expected results:

withQuery('http://localhost:3000', { filters: [{ id: 1}, { name: 'ufo' }] })
// 'http://localhost:3000?filters=%7B+id%3A+1%7D&filters=%7B+name%3A+%27ufo%27+%7D'

I have a similar issue I am facing with this along with using ohmyfetch for Nuxt 3.

Previous in Nuxt 2 using Axios I could build a query string URL which included the array/bracket syntax

const params = {
    page: 1,
    direction: 'desc',
    filter: ['foo'],
    inputs: ['bar'],
}
$axios.get('/api', { params })

would build me a URL like:

http://localhost:8000/api?fields[]=foo&inputs[]=bar

Now doing similar with $fetch its unable to add those, making it not work with something like my Laravel API back-end which expects an array.

$fetch('/api', { method: 'GET', params })
http://localhost:8000/api?fields=foo&inputs=bar

Hello,

@Kapcash

withQuery('http://localhost:3000', { filters: [{ id: 1}, { name: 'ufo' }] })
// 'http://localhost:3000?filters=[object+Object]&filters=[object+Object]'

Not sure where did you get that? I double-checked all popular libraries and this isn't supported or neither the standard?

new URLSearchParams({
  filters: [{ id: 1 }, { name: 'ufo' }],
}).toString();

// 'filters=%5Bobject+Object%5D%2C%5Bobject+Object%5D'

@tcampbPPU

Previous in Nuxt 2 using Axios I could build a query string URL which included the array/bracket syntax

const params = {
    page: 1,
    direction: 'desc',
    filter: ['foo'],
    inputs: ['bar'],
}
$axios.get('/api', { params })
would build me a URL like:

http://localhost:8000/api?fields[]=foo&inputs[]=bar
new URLSearchParams({
  page: 1,
  direction: 'desc',
  filter: ['foo'],
  inputs: ['bar'],
}).toString();

// 'page=1&direction=desc&filter=foo&inputs=bar'

withQuery('http://localhost:8000', {
  page: 1,
  direction: 'desc',
  filter: ['foo'],
  inputs: ['bar'],
});

// 'http://localhost:8000?page=1&direction=desc&filter=foo&inputs=bar'

What's the issue?

Anyways, maybe using https://github.com/sindresorhus/query-string#arrayformat something like is better as there are multiple ways to represent arrays in query string...

@pi0 should be such options integrated inside ufo?

Thanks!

Hm yeah it may not be a standard feature. I'm comparing to axios which does it:

axios.get('http://localhost:3000', { params: { filter: [{ id: 1 }, { name: 'ufo' }] } })
// http://localhost:3000/?filter[]=%7B%22id%22:1%7D&filter[]=%7B%22name%22:%22ufo%22%7D

So that's more a feature request rather than a bug ๐Ÿ˜„

For the moment I use a custom onRequest hook to work around the problem and serialize the parameters this way:

const apiFetch = $fetch.create({
  onRequest({ request, options }) {
    paramsSerializer(options.params);
  }
})

function paramsSerializer(params?: SearchParams): void {
  if (!params) { return; }

  Object.entries(params).forEach(([key, val]) => {
    if (typeof val === 'object' && Array.isArray(val) && val !== null) {
      params[key + '[]'] = val.map(v => JSON.stringify(v));
      delete params[key];
    }
  });
}