I have an object:
{"f":{"cid":"325","field_name[10][0]":"133","field_name[10][1]":"132","price":"320|3600"}}
And I would like to convert this object to query string. I'm using this function:
function toQueryString(obj, prefix) {
var str = [];
for(var p in obj) {
var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
str.push(typeof v == "object" ?
toQueryString(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
return str.join("&");
}
But this function gives me result:
f[cid]=325&f[field_name[10][0]]=133&f[field_name[10][1]]=132&f[price]=320%7C3600
This is wrong as I can't get right result on my server side:
Array
(
[f] => Array
(
[cid] => 325
[field_name[10] => Array
(
[0] => 133
)
[price] => 320|3600
)
)
How can I solve this problem? I think the right result will be something like this:
f[cid]=325&f[field_name[[10][0]]]=133&f[field_name[[10][1]]]=132&f[price]=320%7C3600
I have an object:
{"f":{"cid":"325","field_name[10][0]":"133","field_name[10][1]":"132","price":"320|3600"}}
And I would like to convert this object to query string. I'm using this function:
function toQueryString(obj, prefix) {
var str = [];
for(var p in obj) {
var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
str.push(typeof v == "object" ?
toQueryString(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
return str.join("&");
}
But this function gives me result:
f[cid]=325&f[field_name[10][0]]=133&f[field_name[10][1]]=132&f[price]=320%7C3600
This is wrong as I can't get right result on my server side:
Array
(
[f] => Array
(
[cid] => 325
[field_name[10] => Array
(
[0] => 133
)
[price] => 320|3600
)
)
How can I solve this problem? I think the right result will be something like this:
f[cid]=325&f[field_name[[10][0]]]=133&f[field_name[[10][1]]]=132&f[price]=320%7C3600
Share
Improve this question
edited Oct 1, 2014 at 13:58
Scimonster
33.4k10 gold badges79 silver badges91 bronze badges
asked Sep 28, 2014 at 12:11
XTRUST.ORGXTRUST.ORG
3,4024 gold badges36 silver badges62 bronze badges
7
- 1 What kind of output are you looking to get? – MeLight Commented Sep 28, 2014 at 12:20
- @melight I am going to guess based on the tags that the OP wants a url query string that php will understand as a multidimensional array when it parses the GET variables. – Tim Seguine Commented Sep 28, 2014 at 12:24
- 2 I'd suggest (unless you are constrained) to instead pass it as urlencoded json. It is probably going to be less tricky to get right. You have to explicitly decode the json on the php side though – Tim Seguine Commented Sep 28, 2014 at 12:28
- Barring that, I believe I remember a jquery plugin that does this. Serialize object, I think it is called. – Tim Seguine Commented Sep 28, 2014 at 12:34
-
2
As @TimSeguine suggested, you can use
JSON.stringify()
if you need a pure JavaScript solution. – MeLight Commented Sep 28, 2014 at 13:09
5 Answers
Reset to default 9 +50I changed your function a little in order to correct the nested query strings:
function toQueryString(obj, prefix) {
var str = [], k, v;
for(var p in obj) {
if (!obj.hasOwnProperty(p)) {continue;} // skip things from the prototype
if (~p.indexOf('[')) {
k = prefix ? prefix + "[" + p.substring(0, p.indexOf('[')) + "]" + p.substring(p.indexOf('[')) : p;
// only put whatever is before the bracket into new brackets; append the rest
} else {
k = prefix ? prefix + "[" + p + "]" : p;
}
v = obj[p];
str.push(typeof v == "object" ?
toQueryString(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
return str.join("&");
}
Running this function on your original object now gives us this query string:
f[cid]=325&f[field_name][10][0]=133&f[field_name][10][1]=132&f[price]=320|3600
If we pass this to a PHP page told to print_r($_GET)
, it gives us:
Array
(
[f] => Array
(
[cid] => 325
[field_name] => Array
(
[10] => Array
(
[0] => 133
[1] => 132
)
)
[price] => 320|3600
)
)
Exactly what you wanted, right?
This question already has an answer that does what you want, but I decided to explain the alternative that I hinted at in my ment because I think it is good to know more than one way of doing things.
It doesn't do what you want exactly, but I think it is a simpler, robuster, and more maintainable method of transmitting arbitrary objects.
function toQueryString(obj, name) {
return encodeURIComponent(name) + '=' +
encodeURIComponent(JSON.stringify(obj));
}
On the php side (assuming name
was "foo"
), all you have to do is:
$foo=json_decode($_GET["foo"], true);
The only bit of difficulty is that if you want to support certain versions of Internet Explorer, you have to use a polyfill for JSON.stringify
, but these are readily available.
The drawback is naturally an extra indirection, but I think there is a major benefit: you are pushing the burden of bug testing this to the browser manufacturers and (if necessary) the developers of whatever implementation of JSON.stringify
you decide to use.
Granted that has the drawback of introducing a new dependency, but I believe it is useful enough to warrant it.
Your mileage may vary.
Also: if you can send the data using a POST request, than you can directly send the result of JSON.stringify
as raw POST data without URL encoding it. In the PHP side you can fetch it with json_decode(file_get_contents("php://input"), true)
I just wrote this. It works for me.
let objToQueryString = function (obj, prefix) {
let fields = [];
if (obj && Object.keys(obj).length) {
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
if (typeof obj[i] === 'object') {
fields.push(objToQueryString(obj[i], prefix ? prefix + '[' + i + ']' : i));
} else {
fields.push((prefix ? prefix + '[' + i + ']' : i) + '=' + (typeof obj[i] === 'undefined' ? '' : encodeURIComponent(obj[i])));
}
}
}
} else if (prefix) {
fields.push(prefix + '=');
}
return fields.join('&');
};
objToQueryString({x: 1, y: 2, z: {a: 10, b: 20, c: {i: 100, j: null, k: {}}}}); //returns "x=1&y=2&z[a]=10&z[b]=20&z[c][i]=100&z[c][j]=&z[c][k]="
Enjoy.
TypeScript
declare global {
interface Object {
queryString: () => string;
}
}
if (!Object.prototype.queryString) {
Object.defineProperty(Object.prototype, 'queryString', {
value: function () {
var parts = [];
let obj = this;
for (var key in obj) {
if (typeof obj[key] == 'object') {
for (var key2 in obj[key]) {
parts.push(`${encodeURIComponent(key)}[${encodeURIComponent(key2)}]` + '=' + encodeURIComponent(obj[key][key2]));
}
} else if (typeof obj[key] == 'string') {
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]));
}
}
return "?" + parts.join('&');
}
});
}
input: {"test":{"convert":"querystring"}}
output: test[convert]=querystring
function solution(inputString, objectName)
{
var startingIndex = inputString.replace(/'/g, "").indexOf('{')
var endingIndex = inputString.replace(/'/g, "").indexOf('}')
var propertyValuePairs = inputString.replace(/'/g, "").substring(startingIndex + 1, endingIndex ).split(',')
var propertyValues = new Array();
$.each(propertyValuePairs , function(index, element){
var elements = element.split(':'); propertyValues.push({property: elements[0], value: elements[1]});
});
var result = "";
for (var i = 0; i < propertyValues.length; i++) {
result += objectName + "[" + propertyValues[i].property + "]" + "=" + propertyValues[i].value + "&";
}
return result.substring(0, result.length - 1);
}