jgauffin
jgauffin

Reputation: 101150

Convert JavaScript object into URI-encoded string

I got a JavaScript object which I would like to get x-www-form-urlencoded.

Something like $('#myform').serialize() but for objects.

The following object:

{
    firstName: "Jonas",
    lastName: "Gauffin"
}

would get encoded to:

firstName=Jonas&lastName=Gauffin (do note that special characters should get encoded properly)

Upvotes: 70

Views: 89911

Answers (12)

snitz
snitz

Reputation: 1

create a function to parse the query params.

const parseQueryParams = (query) => {
  return Object.entries(query)
    .map(([key, value]) => key + '=' + encodeURIComponent(value))
    .join('&')
}

Upvotes: 0

Vaibhav C
Vaibhav C

Reputation: 19

let urlParameters = Object.entries(data).map(e => e.join('=')).join('&');

Try using this.

Upvotes: 0

BaseZen
BaseZen

Reputation: 8718

Same as above in effect, but functional style gives an elegant expression::

const to_encoded = obj => Object.keys(obj).map(k =>
    `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');

Upvotes: 4

Nadhas
Nadhas

Reputation: 5807

function jsonToURI(jsonObj) {
    var output = '';
    var keys = Object.keys(jsonObj);
    keys.forEach(function(key) {
        output = output + key + '=' + jsonObj[key] + '&';
    })
    return output.slice(0, -1);
}

function uriToJSON(urijson) {
    var output = {};
    urijson = decodeURIComponent(urijson);
    urijson = urijson.split('&');
    urijson.forEach(function(param) {
        var param = param.split('=');
        output[param[0]] = param[1];
    })
    return output
}

Upvotes: 1

tipster
tipster

Reputation: 796

I'm surprised that no one has mentioned URLSearchParams

var prms = new URLSearchParams({
  firstName: "Jonas",
  lastName: "Gauffin"
});
console.log(prms.toString());
// firstName=Jonas&lastName=Gauffin

Upvotes: 78

johnny 5
johnny 5

Reputation: 20995

To build on @Claymore's answer, Here is a function to encode an object and additionally omit the trailing ampersand:

encodeObject(params) {
  var query = [];
  for (let key in params) {
    let val = encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
    query.push(val);
  }
  return query.join('&');
}

Upvotes: 2

Grallen
Grallen

Reputation: 1670

Please look closely at both answers I provide here to determine which fits you best.


Answer 1:

Likely what you need: Readies a JSON to be used in a URL as a single argument, for later decoding.

jsfiddle

encodeURIComponent(JSON.stringify({"test1":"val1","test2":"val2"}))+"<div>");

Result:

%7B%22test%22%3A%22val1%22%2C%22test2%22%3A%22val2%22%7D

For those who just want a function to do it:

function jsonToURI(json){ return encodeURIComponent(JSON.stringify(json)); }

function uriToJSON(urijson){ return JSON.parse(decodeURIComponent(urijson)); }

Answer 2:

Uses a JSON as a source of key value pairs for x-www-form-urlencoded output.

jsfiddle

// This should probably only be used if all JSON elements are strings
function xwwwfurlenc(srcjson){
    if(typeof srcjson !== "object")
      if(typeof console !== "undefined"){
        console.log("\"srcjson\" is not a JSON object");
        return null;
      }
    u = encodeURIComponent;
    var urljson = "";
    var keys = Object.keys(srcjson);
    for(var i=0; i <keys.length; i++){
        urljson += u(keys[i]) + "=" + u(srcjson[keys[i]]);
        if(i < (keys.length-1))urljson+="&";
    }
    return urljson;
}

// Will only decode as strings
// Without embedding extra information, there is no clean way to
// know what type of variable it was.
function dexwwwfurlenc(urljson){
    var dstjson = {};
    var ret;
    var reg = /(?:^|&)(\w+)=(\w+)/g;
    while((ret = reg.exec(urljson)) !== null){
        dstjson[ret[1]] = ret[2];
    }
    return dstjson;
}

Upvotes: 65

andraaspar
andraaspar

Reputation: 876

An extension to @Grallen's Answer 1 – if you need a shorter URL:

Input:

{"q":"SomethingTM","filters":[{"kind":"A","q":"foobar"},{"kind":"B","isntIt":true}],"pagenumber":1}

Output:

('q'~'SomethingTM'_'filters'~!('kind'~'A'_'q'~'foobar')_('kind'~'B'_'isntIt'~true)*_'pagenumber'~1)

Instead of:

%7B%22q%22%3A%22SomethingTM%22%2C%22filters%22%3A%5B%7B%22kind%22%3A%22A%22%2C%22q%22%3A%22foobar%22%7D%2C%7B%22kind%22%3A%22B%22%2C%22isntIt%22%3Atrue%7D%5D%2C%22pagenumber%22%3A1%7D

function jsonToUri(v, r, s) {
  return encodeURIComponent(
    JSON.stringify(v, r, s)
    .replace(/[()'~_!*]/g, function(c) {
      // Replace ()'~_!* with \u0000 escape sequences
      return '\\u' + ('0000' + c.charCodeAt(0).toString(16)).slice(-4)
    })
    .replace(/\{/g, '(')    //    { -> (
    .replace(/\}/g, ')')    //    } -> )
    .replace(/"/g,  "'")    //    " -> '
    .replace(/\:/g, '~')    //    : -> ~
    .replace(/,/g,  '_')    //    , -> _
    .replace(/\[/g, '!')    //    [ -> !
    .replace(/\]/g, '*')    //    ] -> *
  )
}

function uriToJson(t, r) {
  return JSON.parse(
    decodeURIComponent(t)
    .replace(/\(/g, '{')    //    ( -> {
    .replace(/\)/g, '}')    //    ) -> }
    .replace(/'/g,  '"')    //    ' -> "
    .replace(/~/g,  ':')    //    ~ -> :
    .replace(/_/g,  ',')    //    _ -> ,
    .replace(/\!/g, '[')    //    ! -> [
    .replace(/\*/g, ']')    //    * -> ]
    , r
  )
}



//////// TESTS ////////



var a = {q: 'SomethingTM', filters: [{kind: 'A', q: 'foobar'}, {kind: 'B', isntIt: true}], pagenumber: 1}
var b = jsonToUri(a)
var c = uriToJson(b)

console.log(b)
// ('q'~'SomethingTM'_'filters'~!('kind'~'A'_'q'~'foobar')_('kind'~'B'_'isntIt'~true)*_'pagenumber'~1)

console.log(JSON.stringify(c))
// {"q":"SomethingTM","filters":[{"kind":"A","q":"foobar"},{"kind":"B","isntIt":true}],"pagenumber":1}

var a2 = {"q":"Something(TM)","filters":[{"kind":"A*","q":"foo_bar"},{"kind":"B!","isn'tIt":true}],"page~number":1}
var b2 = jsonToUri(a2)
var c2 = uriToJson(b2)

console.log(b2)
// ('q'~'Something%5Cu0028TM%5Cu0029'_'filters'~!('kind'~'A%5Cu002a'_'q'~'foo%5Cu005fbar')_('kind'~'B%5Cu0021'_'isn%5Cu0027tIt'~true)*_'page%5Cu007enumber'~1)

console.log(JSON.stringify(c2))
// {"q":"Something(TM)","filters":[{"kind":"A*","q":"foo_bar"},{"kind":"B!","isn'tIt":true}],"page~number":1}

Upvotes: 4

Curt
Curt

Reputation: 179

FYI, the accepted answer doesn't include support for nested objects. Here's one way that you can accomplish this:

function xwwwfurlenc(srcjson, parent=""){
    if(typeof srcjson !== "object")
      if(typeof console !== "undefined"){
        console.log("\"srcjson\" is not a JSON object");
        return null;
    }

    let u = encodeURIComponent;
    let urljson = "";
    let keys = Object.keys(srcjson);

    for(let i=0; i < keys.length; i++){
      let k = parent ? parent + "[" + keys[i] + "]" : keys[i];

      if(typeof srcjson[keys[i]] !== "object"){
        urljson += u(k) + "=" + u(srcjson[keys[i]]);
      } else {
        urljson += xwwwfurlenc(srcjson[keys[i]], k)
      }
      if(i < (keys.length-1))urljson+="&";
    }

    return urljson;
}

Upvotes: 3

kmuenkel
kmuenkel

Reputation: 2789

Since you were asking for a serialized object, this is probably slightly off the mark. But just in case, if your intent is to use the values within that object as individual parameters, this might be the conversion you're looking for:

var params = {
    "param1": "arg1",
    "param2": "arg2"
};
var query = "";
for (key in params) {
    query += encodeURIComponent(key)+"="+encodeURIComponent(params[key])+"&";
}
xmlhttp.send(query);

Upvotes: 22

jb10210
jb10210

Reputation: 1176

See jQuery.param(...). Converts to uri, see link for more information!

Upvotes: 22

ShankarSangoli
ShankarSangoli

Reputation: 69905

You need to use JSON.stringify() to serialize the JSON/JavaScript object.

It is natively available in almost all the modern browsers but you can include the below js which will add the required library incase it is not available.

http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js

Upvotes: -5

Related Questions