Martial Martial - 24 days ago 7
Node.js Question

req.body automatically cast array to object after 20 entries

In my form I can add as many properties as I want dynamically:

<form action="">
<div class="property">
<label>Name : <input type="text" name="properties[1][name]"></label>
<label>Order : <input type="text" name="properties[1][order]"></label>
<label>Label : <input type="text" name="properties[1][label]"></label>
<label>Type : <input type="text" name="properties[1][type]"></label>
<label>Description : <textarea name="properties[1][description]"></textarea></label>
</div>
<div class="property">
<label>Name : <input type="text" name="properties[2][name]"></label>
<label>Order : <input type="text" name="properties[2][order]"></label>
<label>Label : <input type="text" name="properties[2][label]"></label>
<label>Type : <input type="text" name="properties[2][type]"></label>
<label>Description : <textarea name="properties[2][description]"></textarea></label>
</div>
<div class="property">
<label>Name : <input type="text" name="properties[3][name]"></label>
<label>Order : <input type="text" name="properties[3][order]"></label>
<label>Label : <input type="text" name="properties[3][label]"></label>
<label>Type : <input type="text" name="properties[3][type]"></label>
<label>Description : <textarea name="properties[3][description]"></textarea></label>
</div>
...
</form>


In node.js, I want to do a
forEach
on
req.body.properties
but with more than 20 properties,
req.body.properties
is somehow cast in
Object
and
forEach
function does not exist anymore.

propUpdate: (req, res) => {
const post = req.body;
console.log('isArray :', Array.isArray(post.properties));
console.log('isObject :', require('lodash').isObject(post.properties));
console.log('properties :', post.properties);
...
}


Here is the result with 20 properties or less :

isArray : true
isObject : true
properties : [ { name: 'test 1',
order: '1',
label: 'label 1',
type: 'type 1' },
{ name: 'test 2',
order: '2',
label: 'label 2',
type: 'type 2' },
....
{ name: 'test 20',
order: '20',
label: 'label 20',
type: 'type 20' } ]


And with more than 20 properties :

isArray : false
isObject : true
properties : { '1' :
{ name: 'test 1',
order: '1',
label: 'label 1',
type: 'type 1' },
'2' :
{ name: 'test 2',
order: '2',
label: 'label 2',
type: 'type 2' },
....
'21' :
{ name: 'test 21',
order: '21',
label: 'label 21',
type: 'type 21' } }


I would like to understand why node.js have this behavior and how avoid it.
Is anyone can help me ?

PS : I had to reduce my code example because stackoverflow does not like having more code than explanation. Hope this is still understandable.

Answer

body-parser (which handles request bodies) uses the qs library to parse URL-encoded data.

The documentation for that library states, about arrays:

qs will also limit specifying indices in an array to a maximum index of 20. Any array members with an index of greater than 20 will instead be converted to an object with the index as the key

...

This limit can be overridden by passing an arrayLimit option

However, there doesn't seem to be a way of passing that option to qs through body-parser. But it's relatively easy to convert the object to an array:

post.properties.length = Object.keys(post.properties).length;
let properties = Array.from(post.properties);
Comments