Francesco Orsi
Francesco Orsi

Reputation: 2089

axios + query-string vs. jQuery, POST data broken by query-string

data example we want to send by ajax

const dataExample = {
    "userId": '...id',
    "supportFormId": 14,
    "supportFormName": 'Tickets',
    "customFields": [
        {
            "customFieldId": 80,
            "name": 'Subject',
            "value": '...',
            "dataType": 'Text'
        },
        // ....
        {
            "customFieldId": 84,
            "name": 'Description',
            "value": '...',
            "dataType": 'Text'
        }
    ]
}

jQuery ajax call


$.ajax({
    type: 'post',
    url: 'http://....',
    dataType: 'json',
    data: dataExample,
    success: function (data) { /* ... */ }
});

axios + query-string ajax call


import axios from "axios";
import qs from 'query-string'

const dataQs = qs.stringify(dataExample);

return new Promise(
    async (resolve, reject) => {
        try {
            const response = await axios({
                method: 'post',
                headers: { 'content-type': 'application/x-www-form-urlencoded' },
                data: dataQs,
                url: 'http://....'
            });
            if (response) return resolve(response)
            return reject()
        } catch (err) { return reject(err) }
    }
);

result

result

question

jQuery never has any type of problem but axios + query-string, despite different headers like

'content-type': 'application/json',
'content-type': 'multipart/form-data',

and/or optional stringify options like

const dataQs = qs.stringify(data, { encode: false })
const dataQs = qs.stringify(data, { arrayFormat: 'indices', commaSuffix: 'bracket' })
const dataQs = qs.stringify(data, { arrayFormat: 'indices' })
const dataQs = qs.stringify(data, { arrayFormat: 'brackets' })
const dataQs = qs.stringify(data, { arrayFormat: 'repeat' })
const dataQs = qs.stringify(data, { arrayFormat: 'comma' })

breaks the data all the times..

which is the correct axios + query-string (or alternative) code to get the same result of jQuery?

Upvotes: 2

Views: 589

Answers (1)

Tarun Lalwani
Tarun Lalwani

Reputation: 146500

You can use something like below

const objectToQueryString = (initialObj) => {
    const reducer = (obj, parentPrefix = null) => (prev, key) => {
      const val = obj[key];
      key = encodeURIComponent(key);
      const prefix = parentPrefix ? `${parentPrefix}[${key}]` : key;

      if (val == null || typeof val === 'function') {
        prev.push(`${prefix}=`);
        return prev;
      }

      if (['number', 'boolean', 'string'].includes(typeof val)) {
        prev.push(`${prefix}=${encodeURIComponent(val)}`);
        return prev;
      }

      prev.push(Object.keys(val).reduce(reducer(val, prefix), []).join('&'));
      return prev;
    };

    return Object.keys(initialObj).reduce(reducer(initialObj), []).join('&');
  };

  objectToQueryString({
    name: 'John Doe',
    age: 20,
    children: [
      { name: 'Foo Doe' },
      { name: 'Bar Doe' }
    ],
    wife: {
      name: 'Jane Doe'
    }
  });
  // -> name=John%20Doe&age=20&children[0][name]=Foo%20Doe&children[1][name]=Bar%20Doe&wife[name]=Jane%20Doe

Taken from below gist

https://gist.github.com/tjmehta/9204891

Upvotes: 3

Related Questions