Reputation: 3875
Exampple of application/x-www-form-urlencoded string
CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4
(Decoded)
CorrelationId=1&PickedNumbers[]=1&PickedNumbers[]=2&PickedNumbers[]=3&PickedNumbers[]=4
Into JSON
var gamePlayData = {
CorrelationId: gameId,
PickedNumbers: ["1","2","3","4"]
};
Upvotes: 33
Views: 76254
Reputation: 223
You can use qs library if you're using node, or browserify.
var qs = require('qs')
var encodedString = "CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4"
console.log(qs.parse(encodedString))
// { CorrelationId: '1', PickedNumbers: [ '1', '2', '3', '4' ] }
Upvotes: 15
Reputation: 126
In typescript, works for me:
Use qs.parse to transform in object ParsedQs.
Use as unknow to implicit type unknow and before force convert to string.
Use JSON.parse to convert an string to object.
It was useful to use validations with Joi.
const payload = JSON.parse(JSON.stringify(qs.parse(request.body) as unknown as string));
Payload (cURL):
--data-urlencode 'notification=123-456123' \
--data-urlencode 'test=123456' \
--data-urlencode 'ajieoajeoa=Lorem ipsum'
Result:
{
notification: '123-456123',
test: '123456',
ajieoajeoa: 'Lorem ipsum'
}
Upvotes: 0
Reputation: 350
Updated answer for 2022, works both in the browser and in node.
Use URLSearchParams
class.
Note: The param name
PickedNumbers%5B%5D
will turn to be the literal stringPickedNumbers[]
. You don't need to encode the brackets in order to make it an array
const paramsStr = 'CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4';
const params = new URLSearchParams(paramsStr);
//access a specific param
console.log(params.get('PickedNumbers[]')); // '4'
console.log(params.getAll('PickedNumbers[]')); // ['1','2','3','4']
const o = Object.fromEntries(Array.from(params.keys()).map(k => [k, params.getAll(k).length===1 ? params.get(k) : params.getAll(k)]));
console.log(JSON.stringify(o)); //full object
Upvotes: 7
Reputation: 1
var jsonMessage = "{\"".concat(message.replace("&", "\",\"").replace("=", "\":\"")).concat("\"}");
Upvotes: 0
Reputation: 35473
A one-liner:
let s = 'a=1&b=2&c=3';
Object.fromEntries(
s.split('&')
.map(s => s.split('='))
.map(pair => pair.map(decodeURIComponent)))
// -> {a: "1", b: "2", c: "3"}
and if you want repeated parameters to be represented as arrays:
let s = 'a=1&b=2&c[]=3&c[]=4&c[]=5&c[]=6';
s
.split('&')
.map(s => s.split('='))
.map(pair => pair.map(decodeURIComponent))
.reduce((memo, [key, value]) => {
if (!(key in memo)) { memo[key] = value; }
else {
if (!(memo[key] instanceof Array))
memo[key] = [memo[key], value];
else
memo[key].push(value);
}
return memo;
}, {})
// -> {"a":"1","b":"2","c[]":["3","4","5","6"]}
Upvotes: 2
Reputation: 5
public static void Main()
{
string str ="RESULT=0&PNREF=A10AABBF8DF2&RESPMSG=Approved&AUTHCODE=668PNI&PREFPSMSG=No Rules Triggered&POSTFPSMSG=No Rules Triggered";
var sr = str.Replace("&", "=");
string[] sp = sr.Split('=');
var spl = sp.Length;
int n = 1;
var ss = "{";
for (var k = 0; k < spl; k++)
{
if (n % 2 == 0)
{
if (n == spl)
{
ss += '"' + sp[k] + '"';
}
else
{
ss += '"' + sp[k] + '"' + ",";
}
}
else
{
ss += '"' + sp[k] + '"' + ":";
}
n++;
}
ss += "}";
Console.WriteLine(ss);
}
Upvotes: -3
Reputation: 8188
This is a core module of Node.js now: https://nodejs.org/api/querystring.html#querystring_querystring_parse_str_sep_eq_options
var qs = require('querystring')
var json = qs.parse('why=not&sad=salad')
// { why: 'not', sad: 'salad' }
Works with encoded characters too:
var json2 = qs.parse('http%3A%2F%2Fexample.com&sad=salad')
// { url: 'http://example.com', sad: 'salad' }
Upvotes: 37
Reputation: 7019
You need the opposite of jQuery.param. One of the options is http://benalman.com/code/projects/jquery-bbq/examples/deparam/
Upvotes: 0
Reputation: 76433
I've been dealing with this recently: I had to parse data that could contain objects nested up to 5 levels deep. I needed the code to be able to deal with both rather complex data, but not fail to decode a URI as simple as id=213
.
I spent quite some time on google, trying to find a (semi-)elegant solution to this problem, and this question kept showing up. Since it gets 1 view/day (give or take) I've decided to post my solution here, hope it helps someone out:
function form2Json(str)
{
"use strict";
var obj,i,pt,keys,j,ev;
if (typeof form2Json.br !== 'function')
{
form2Json.br = function(repl)
{
if (repl.indexOf(']') !== -1)
{
return repl.replace(/\](.+?)(,|$)/g,function($1,$2,$3)
{
return form2Json.br($2+'}'+$3);
});
}
return repl;
};
}
str = '{"'+(str.indexOf('%') !== -1 ? decodeURI(str) : str)+'"}';
obj = str.replace(/\=/g,'":"').replace(/&/g,'","').replace(/\[/g,'":{"');
obj = JSON.parse(obj.replace(/\](.+?)(,|$)/g,function($1,$2,$3){ return form2Json.br($2+'}'+$3);}));
pt = ('&'+str).replace(/(\[|\]|\=)/g,'"$1"').replace(/\]"+/g,']').replace(/&([^\[\=]+?)(\[|\=)/g,'"&["$1]$2');
pt = (pt + '"').replace(/^"&/,'').split('&');
for (i=0;i<pt.length;i++)
{
ev = obj;
keys = pt[i].match(/(?!:(\["))([^"]+?)(?=("\]))/g);
for (j=0;j<keys.length;j++)
{
if (!ev.hasOwnProperty(keys[j]))
{
if (keys.length > (j + 1))
{
ev[keys[j]] = {};
}
else
{
ev[keys[j]] = pt[i].split('=')[1].replace(/"/g,'');
break;
}
}
ev = ev[keys[j]];
}
}
return obj;
}
I've tested it, with data like the string below (4 levels deep):
str = "id=007&name[first]=james&name[last]=bond&name[title]=agent&personalia[occupation]=spy&personalia[strength]=women&personalia[weakness]=women&tools[weapons][close][silent]=garrot&tools[weapons][medium][silent]=pistol_supressed&tools[weapons][medium][loud]=smg&tools[weapons][far][silent]=sniper&tools[movement][slow]=foot&tools[movement][far]=DBS";
Which neatly returns an object, that, when passed through JSON.stringify
comes out like this:
{"id":"007","name":{"title":"agent","first":"james","last":"bond"},"personalia":{"weakness":"women","occupation":"spy","strength":"women"},"tools":{"movement":{"far":"DBS","slow":"foot"},"weapons":{"close":{"silent":"garrot"},"medium":{"silent":"pistol_supressed","loud":"smg"},"far":{"silent":"sniper"}}}}
It passes a JSlint check, when ignoring white space, .
and [^...]
and accepting ++
. All in all, I'd consider that to be acceptable.
Upvotes: 16
Reputation: 8390
Here's a pure-JavaScript way to do it. JavaScript frameworks might also help you out with this. EDIT: Just for kicks, I threw in dictionary parsing, too. See the 2nd example.
function decodeFormParams(params) {
var pairs = params.split('&'),
result = {};
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('='),
key = decodeURIComponent(pair[0]),
value = decodeURIComponent(pair[1]),
isArray = /\[\]$/.test(key),
dictMatch = key.match(/^(.+)\[([^\]]+)\]$/);
if (dictMatch) {
key = dictMatch[1];
var subkey = dictMatch[2];
result[key] = result[key] || {};
result[key][subkey] = value;
} else if (isArray) {
key = key.substring(0, key.length-2);
result[key] = result[key] || [];
result[key].push(value);
} else {
result[key] = value;
}
}
return result;
}
decodeFormParams("CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4");
// => {"CorrelationId":"1","PickedNumbers":["1","2","3","4"]}
decodeFormParams("a%5Bb%5D=c&a%5Bd%5D=e");
// => {"a":{"b":"c","d":"e"}}
Upvotes: 3
Reputation: 26183
the following code should do the trick:
var str = 'CorrelationId=1&PickedNumbers%5B%5D=1&PickedNumbers%5B%5D=2&PickedNumbers%5B%5D=3&PickedNumbers%5B%5D=4';
var keyValuePairs = str.split('&');
var json = {};
for(var i=0,len = keyValuePairs.length,tmp,key,value;i <len;i++) {
tmp = keyValuePairs[i].split('=');
key = decodeURIComponent(tmp[0]);
value = decodeURIComponent(tmp[1]);
if(key.search(/\[\]$/) != -1) {
tmp = key.replace(/\[\]$/,'');
json[tmp] = json[tmp] || [];
json[tmp].push(value);
}
else {
json[key] = value;
}
}
Upvotes: 6
Reputation: 38147
Try this->
// convert string to object
str = 'a=6&id=99';
var arr = str.split('&');
var obj = {};
for(var i = 0; i < arr.length; i++) {
var bits = arr[i].split('=');
obj[bits[0]] = bits[1];
}
//alert(obj.a);
//alert(obj.id);
// convert object back to string
str = '';
for(key in obj) {
str += key + '=' + obj[key] + '&';
}
str = str.slice(0, str.length - 1);
alert(str);
Or use this (JQuery) http://api.jquery.com/jQuery.param/
Upvotes: 1