Search code examples
javascriptexpressurlsearchparams

URLSearchParams fails to append array


Hi I'm having issues sending an array with URLSearchParams. My code is as follows:

const worker = async(endpoint, method, parameters) => {
    let body;
    if (typeof parameters === 'object' && parameters !== null) {
        body = new URLSearchParams()
        for (const key in parameters) {
            body.append(key, parameters[key])
        }
    }

    try {
        const response = await fetch(endpoint, {
            method: method,
            body: body || null
        });

        const json = await response.json();
        if (json.status === 200) {
            return Promise.resolve(json.data)
        }

        return Promise.reject(json.message);
    } catch(error) {
        return Promise.reject('500 Encountered a server error')
    }
};

I iterate the parameters object and create a new URLSearchParams object. One of my parameters is an array I have logged the value of the parameter just before body.append(key, parameters[key]) is executed and it is indeed an array: Array(1) ["user"]. However when I check my express server and read the response the value of the parameter is "user" and not ["user"]. I have confirmed it isn't an issue with my express server because the same request works in Postman. What am I doing wrong here?


Solution

  • You can only append strings to a URL.

    If you pass an array as the argument to append it will be stringified (with an implicit call to the toString method, which is equivalent to .join(",").

    If you want to pass an array of data, then you need to encode it somehow. How you do that depends on how you backend expects the data to be encoded.

    The traditional approach is to use duplicate keys:

    const myArray = parameters[key];
    myArray.forEach(value => body.append(key, value)
    

    The PHP approach, which is supported by the body-parser module with the extended option, is to make sure the key ends in the characters [] so that the data is flagged as being an array even if there is only one item in it.

    const myArray = parameters[key];
    myArray.forEach(value => body.append(`${key}[]`, value);
    

    You implied that you expect the value to include square brackets, which suggests you are wanting the array to be JSON encoded, in which case you have to do that explicitly:

     body.append(key, JSON.stringify(parameters[key]))