Flatten a javascript object to pass as querystring

JavascriptJqueryJavascript ObjectsFlatten

Javascript Problem Overview


I have a javascript object that I need to flatten into a string so that I can pass as querystring, how would I do that? i.e:

{ cost: 12345, insertBy: 'testUser' } would become cost=12345&insertBy=testUser

I can't use jQuery AJAX call for this call, I know we can use that and pass the object in as data but not in this case. Using jQuery to flatten to object would be okay though.

Thank you.

Javascript Solutions


Solution 1 - Javascript

Here's a non-jQuery version:

function toQueryString(obj) {
    var parts = [];
    for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
            parts.push(encodeURIComponent(i) + "=" + encodeURIComponent(obj[i]));
        }
    }
    return parts.join("&");
}

Solution 2 - Javascript

You want jQuery.param:

var str = $.param({ cost: 12345, insertBy: 'testUser' });
// "cost=12345&insertBy=testUser"

Note that this is the function used internally by jQuery to serialize objects passed as the data argument.

Solution 3 - Javascript

My ES6 version (pure Javascript, no jQuery):

function toQueryString(paramsObject) {
  return Object
    .keys(paramsObject)
    .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(paramsObject[key])}`)
    .join('&')
  ;
}

Solution 4 - Javascript

This is an old question, but at the top of Google searches, so I'm adding this for completeness.

If 1) you don't want to user jQuery, but 2) you want to covert a nested object to a query string, then (building off of Tim Down and Guy's answers), use this:

function toQueryString(obj, urlEncode) {
    //
    // Helper function that flattens an object, retaining key structer as a path array:
    //
    // Input: { prop1: 'x', prop2: { y: 1, z: 2 } }
    // Example output: [
    //     { path: [ 'prop1' ],      val: 'x' },
    //     { path: [ 'prop2', 'y' ], val: '1' },
    //     { path: [ 'prop2', 'z' ], val: '2' }
    // ]
    //
    function flattenObj(x, path) {
        var result = [];

        path = path || [];
        Object.keys(x).forEach(function (key) {
            if (!x.hasOwnProperty(key)) return;

            var newPath = path.slice();
            newPath.push(key);

            var vals = [];
            if (typeof x[key] == 'object') {
                vals = flattenObj(x[key], newPath);
            } else {
                vals.push({ path: newPath, val: x[key] });
            }
            vals.forEach(function (obj) {
                return result.push(obj);
            });
        });

        return result;
    } // flattenObj

    // start with  flattening `obj`
    var parts = flattenObj(obj); // [ { path: [ ...parts ], val: ... }, ... ]

    // convert to array notation:
    parts = parts.map(function (varInfo) {
        if (varInfo.path.length == 1) varInfo.path = varInfo.path[0];else {
            var first = varInfo.path[0];
            var rest = varInfo.path.slice(1);
            varInfo.path = first + '[' + rest.join('][') + ']';
        }
        return varInfo;
    }); // parts.map

    // join the parts to a query-string url-component
    var queryString = parts.map(function (varInfo) {
        return varInfo.path + '=' + varInfo.val;
    }).join('&');
    if (urlEncode) return encodeURIComponent(queryString);else return queryString;
}

Use like:

console.log(toQueryString({
    prop1: 'x',
    prop2: {
        y: 1,
        z: 2
    }
}, false));

Which outputs:

prop1=x&prop2[y]=1&prop2[z]=2

Solution 5 - Javascript

Here is another non-jQuery version that utilizes lodash or underscore if you're already using one of those libraries:

var toQueryString = function(obj) {
  return _.map(obj,function(v,k){
    return encodeURIComponent(k) + '=' + encodeURIComponent(v);
  }).join('&');
};

^ I wrote that 5 years ago. An updated and more succinct version of this would now (Oct 2019) be:

var input = { cost: 12345, insertBy: 'testUser' };
Object.entries(input)
  .map(([k,v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
  .join('&');
// cost=12345&insertBy=testUser

Check that the runtime that you're targeting supports Object.entries() or that you're using a transpiler like Babel or TypeScript if it doesn't.

Solution 6 - Javascript

Try the $.param() method:

var result = $.param({ cost: 12345, insertBy: 'testUser' });

Solution 7 - Javascript

General JavaScript:

function toParam(obj) {
  var str = "";
  var seperator = "";
  for (key in obj) {
    str += seperator;
    str += enncodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
    seperator = "&";
  }
  return str;
}


toParam({ cost: 12345, insertBy: 'testUser' })
"cost=12345&insertBy=testUser"

Solution 8 - Javascript

Another version:

function toQueryString(obj) {
    return Object.keys(obj).map(k => {
      return encodeURIComponent(k) + "=" + encodeURIComponent(obj[k])
    })
    .join("&");
}

Solution 9 - Javascript

var myObj = { cost: 12345, insertBy: 'testUser' },
    param = '',
    url   = 'http://mysite.com/mypage.php';    

for (var p in myObj) {
  if (myObj.hasOwnProperty(p)) {
    param += encodeURIComponent(p) + "=" + encodeURIComponent(myObj[p]) + "&";
  }
}

window.location.href = url + "?" + param;

Solution 10 - Javascript

you can use this

function serialize(obj)
{
	let str = []

	for(var p in obj)
    {
      if(obj.hasOwnProperty(p)) str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]))
    }

	return str.join('&')
}

try on JSFiddle on this link https://jsfiddle.net/yussan/kwmnkca6/

Solution 11 - Javascript

ES6 version of Jrop's answer (also parses nested params)

const toQueryString = (obj, urlEncode = false) => {
  if (!obj) return null;
  const flattenObj = (x, path = []) => {
    const result = [];
    Object.keys(x).forEach((key) => {
      if (!Object.prototype.hasOwnProperty.call(x, key)) return;
      const newPath = path.slice();
      newPath.push(key);
      let vals = [];
      if (typeof x[key] === 'object') {
        vals = flattenObj(x[key], newPath);
      } else {
        vals.push({ path: newPath, val: x[key] });
      }
      vals.forEach((v) => {
        return result.push(v);
      });
    });
    return result;
  };

  let parts = flattenObj(obj);
  parts = parts.map((varInfo) => {
    if (varInfo.path.length === 1) {
      varInfo.path = varInfo.path[0]; // eslint-disable-line no-param-reassign
    } else {
      const first = varInfo.path[0];
      const rest = varInfo.path.slice(1);
      varInfo.path = `${first}[${rest.join('][')}]`; // eslint-disable-line no-param-reassign
    }
    return varInfo;
  });

  const queryString = parts.map((varInfo) => {
    return `${varInfo.path}=${varInfo.val}`;
  }).join('&');
  if (urlEncode) {
    return encodeURIComponent(queryString);
  }
  return queryString;
};

Solution 12 - Javascript

Using Lodash library it can be done as:

let data = {}

_.map(data, (value, key) => `${key}=${value}`)
.join("&");

> Note that this library has been imported as:

window._ = require('lodash');

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSaxmanView Question on Stackoverflow
Solution 1 - JavascriptTim DownView Answer on Stackoverflow
Solution 2 - JavascriptlonesomedayView Answer on Stackoverflow
Solution 3 - JavascriptMichaël PerrinView Answer on Stackoverflow
Solution 4 - JavascriptJropView Answer on Stackoverflow
Solution 5 - JavascriptGuyView Answer on Stackoverflow
Solution 6 - JavascriptDarin DimitrovView Answer on Stackoverflow
Solution 7 - JavascriptJim BlacklerView Answer on Stackoverflow
Solution 8 - JavascriptblablablaView Answer on Stackoverflow
Solution 9 - JavascriptmVChrView Answer on Stackoverflow
Solution 10 - JavascriptyussanView Answer on Stackoverflow
Solution 11 - JavascriptMythical FishView Answer on Stackoverflow
Solution 12 - JavascriptBedram TamangView Answer on Stackoverflow