qs icon indicating copy to clipboard operation
qs copied to clipboard

Bug Report: `qs.parse` for parsing a string contains both [] and [0].

Open leoyli opened this issue 7 years ago • 4 comments

Bug Report

I think here is a bug: qs.parse for parsing a string contains both [] and [0]. (not being considered as mixing notation)

qs.parse('a[]=na&a[20]=20&a[0]=0') === { a: [ 'na', '20', '0' ] }
qs.parse('a[]=na&a[20]=20&a[10]=10') === { a: [ 'na', '10', '20' ] }
qs.parse('a[20]=20&a[0]=0&a[10]=10') === { a: [ '0', '10', '20' ] }
qs.parse('a[]=na&a[20]=20&a[0]=0&a[10]=10') === { a: [ 'na', '10', '20', '0' ] } // *
qs.parse('a[20]=20&a[]=na&a[0]=0&a[10]=10') === { a: [ 'na', '10', '20', '0' ] } // **

Based on the result above (// * and // **), whenever the string contain a[], then the value will always be preserved a the first member with 0 index; However, if the string contains a[0] at same time, the value of a[0] is always set to the last member in the array, which is unexpected.

I think the value should be either (a) treat a[] is something special, and always the first element, then arrange by specified indexes [ 'na', '0', '10', '20' ] // but it is also somehow inconsistent (see below)

(b) treat a[] as a[0], gives [ ['na', '0'], '10', '20' ]

note, this is how it behaves when arrayLimit: 0 option being set:

qs.parse('a[20]=20&a[]=na&a[0]=0&a[10]=10', { arrayLimit: 0 }) === { a: { '0': [ 'na', '0' ], '10': '10', '20': '20' } }

leoyli avatar May 13 '18 20:05 leoyli

What would you expect from qs.parse('a[]=1&a[0]=2&a[]=3') or qs.parse('a[]=1&a[0]=2&a[]=3&a[1]=4&a[]=5')?

It kind of seems like the current behavior on master is already "all [] always come first, then by-index items".

ljharb avatar May 14 '18 02:05 ljharb

I certainly don't think a[]=1&a[0]=2 should give [1, 2] - a[] always means a new item (I'm not sure why arrayLimit 0 does that).

ljharb avatar May 14 '18 02:05 ljharb

Ok, if a[] is always treated as an independent new item, then the following result met my expectations.

qs.parse('a[]=1&a[0]=2&a[]=3') === { a: [ '1', '3', '2' ] }   // true, expected
qs.parse('a[]=1&a[0]=2&a[]=3&a[1]=4&a[]=5') === { a: [ '1', '3', '5', '2', '4' ] }   // true, expected

But as I posted, it have some weird behaviour:

qs.parse('a[]=new&a[19]=19&a[0]=0&a[10]=10') === { a: [ 'new', '10', '19', '0' ] };  // unexpected
qs.parse('a[19]=19&a[]=new&a[0]=0&a[10]=10') === { a: [ 'new', '10', '19', '0' ] };  // unexpected
qs.parse('a[19]=19&a[0]=0&a[]=new&a[10]=10') === { a: [ '0', '10', '19', 'new' ] };  // unexpected
qs.parse('a[19]=19&a[0]=0&a[10]=10&a[]=new') === { a: [ '0', '10', '19', 'new' ] };  // unexpected
                                             === { a: [ 'new', '0', '10', '19' ] };  // expect all should return this

In above result, the query itself is equivalent because I just shift a[]=new 1 position each time, but the position of a[0] and a[] are exchanged in the last two cases, which is surprising.

And is the behaviour like in arrayLimit 0 are considered as a bug?

leoyli avatar May 14 '18 03:05 leoyli

hello,Do you have any solutions,I'm troubled too

king-bcolor avatar Aug 24 '23 08:08 king-bcolor