是否有任何本机函数将 json 转换为 url 参数?

我需要将 json 对象转换为 url 格式,比如: “旦 = 12 & asd = 1”

我不干了:

        var data = {
'action':'actualiza_resultado',
'postID': 1,
'gl': 2,
'gl2' : 3
};


var string_=JSON.stringify(data);


string_=string_.replace(/{/g, "");
string_=string_.replace(/}/g, "");
string_=string_.replace(/:/g, "=")
string_=string_.replace(/,/g, "&");
string_=string_.replace(/"/g, "");

但是我想知道是否有任何函数在 javascript 或 JSON 对象这样做?

119817 次浏览

You don't need to serialize this object literal.

Better approach is something like:

function getAsUriParameters(data) {
var url = '';
for (var prop in data) {
url += encodeURIComponent(prop) + '=' +
encodeURIComponent(data[prop]) + '&';
}
return url.substring(0, url.length - 1)
}
getAsUriParameters(data); //"action=actualiza_resultado&postID=1&gl=2&gl2=3"

But i wonder if there any function in javascript

Nothing prewritten in the core.

or json to do this?

JSON is a data format. It doesn't have functions at all.


This is a relatively trivial problem to solve though, at least for flat data structures.

Don't encode the objects as JSON, then:

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


alert(obj_to_query({
'action': 'actualiza_resultado',
'postID': 1,
'gl': 2,
'gl2': 3
}));

There isn't a standard way to encode complex data structures (e.g. with nested objects or arrays). It wouldn't be difficult to extend this to emulate the PHP method (of having square brackets in field names) or similar though.

Use the URLSearchParams interface, which is built into browsers and Node.js starting with version 10, released in 2018.

const myParams = {'foo': 'hi there', 'bar': '???'};


const u = new URLSearchParams(myParams).toString();


console.log(u);

Old answer: jQuery provides param that does exactly that. If you don't use jquery, take at look at the source.

Basically, it goes like this:

url = Object.keys(data).map(function(k) {
return encodeURIComponent(k) + '=' + encodeURIComponent(data[k])
}).join('&')

This one processes arrays with by changing the nameinto mutiple name[]

function getAsUriParameters (data) {
return Object.keys(data).map(function (k) {
if (_.isArray(data[k])) {
var keyE = encodeURIComponent(k + '[]');
return data[k].map(function (subData) {
return keyE + '=' + encodeURIComponent(subData);
}).join('&');
} else {
return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]);
}
}).join('&');
};

Like @georg said, you can use JQuery.param for flat objects.

If you need to process complex objects, you can use JsonUri, a python package that does just that. There is JavaScript library for it as well

Disclaimer: I am the author of JSONURI

Edit: I learned much later that you can also just base64 encode your payload - most languages as support for base64 encoding/decoding

Example

x = {name: 'Petter', age: 47, places: ['Mozambique', 'Zimbabwe']}
stringRep = JSON.stringify(x)
encoded = window.btoa(stringRep)

Gives you eyJuYW1lIjoiUGV0dGVyIiwiYWdlIjo0NywicGxhY2VzIjpbIk1vemFtYmlxdWUiLCJaaW1iYWJ3ZSJdfQ==, which you can use as a uri parameter

decoded = window.atob(encoded)
originalX = JSON.parse(decoded)

Needless to say, it comes with its own caveats

Using ES6 syntax:

var data = {
'action':'actualiza_resultado',
'postID': 1,
'gl': 2,
'gl2' : 3
};


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


console.log(urlParameters);

Based on georg's answer, but also adding ? before the string and using ES6:

  const query = !params ? '': Object.keys(params).map((k, idx) => {
let prefix = '';
if (idx === 0) {
prefix = '?';
}
return prefix + encodeURIComponent(k) + '=' + encodeURIComponent(params[k]);
}).join('&');

Something I find nicely looking in ES6:

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

Later update (same thing, maybe a bit cleaner):

const urlfy = obj => Object
.keys(obj)
.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]))
.join('&');

The custom code above only handles flat data. And JQuery is not available in react native. So here is a js solution that does work with multi-level objects and arrays in react native.

function formurlencoded(data) {
const opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};


let sorted = Boolean(opts.sorted),
skipIndex = Boolean(opts.skipIndex),
ignorenull = Boolean(opts.ignorenull),
encode = function encode(value) {
return String(value).replace(/(?:[\0-\x1F"-&\+-\}\x7F-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g, encodeURIComponent).replace(/ /g, '+').replace(/[!'()~\*]/g, function (ch) {
return '%' + ch.charCodeAt().toString(16).slice(-2).toUpperCase();
});
},
keys = function keys(obj) {
const keyarr = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Object.keys(obj);
return sorted ? keyarr.sort() : keyarr;
},
filterjoin = function filterjoin(arr) {
return arr.filter(function (e) {
return e;
}).join('&');
},
objnest = function objnest(name, obj) {
return filterjoin(keys(obj).map(function (key) {
return nest(name + '[' + key + ']', obj[key]);
}));
},
arrnest = function arrnest(name, arr) {
return arr.length ? filterjoin(arr.map(function (elem, index) {
return skipIndex ? nest(name + '[]', elem) : nest(name + '[' + index + ']', elem);
})) : encode(name + '[]');
},
nest = function nest(name, value) {
const type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : typeof value === 'undefined' ? 'undefined' : typeof(value);
let f = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;


if (value === f) f = ignorenull ? f : encode(name) + '=' + f; else if (/string|number|boolean/.test(type)) f = encode(name) + '=' + encode(value); else if (Array.isArray(value)) f = arrnest(name, value); else if (type === 'object') f = objnest(name, value);


return f;
};


return data && filterjoin(keys(data).map(function (key) {
return nest(key, data[key]);
}));

}

I made an implementation that support nested objects and arrays i.e.

var data = {
users: [
{
"name": "jeff",
"tasks": [
"Do one thing",
"Do second thing"
]
},
{
"name": "rick",
"tasks": [
"Never gonna give you up",
"Never gonna let you down"
]
}
]
}

Will be:

users[0][name]=jeff&users[0][tasks][0]=Do%20one%20thing&users[0][tasks][1]=Do%20second%20thing&users[1][name]=rick&users[1][tasks][0]=Never%20gonna%20give%20you%20up&users[1][tasks][1]=Never%20gonna%20let%20you%20down

So, here's the implementation:

var isObj = function(a) {
if ((!!a) && (a.constructor === Object)) {
return true;
}
return false;
};
var _st = function(z, g) {
return "" + (g != "" ? "[" : "") + z + (g != "" ? "]" : "");
};
var fromObject = function(params, skipobjects, prefix) {
if (skipobjects === void 0) {
skipobjects = false;
}
if (prefix === void 0) {
prefix = "";
}
var result = "";
if (typeof(params) != "object") {
return prefix + "=" + encodeURIComponent(params) + "&";
}
for (var param in params) {
var c = "" + prefix + _st(param, prefix);
if (isObj(params[param]) && !skipobjects) {
result += fromObject(params[param], false, "" + c);
} else if (Array.isArray(params[param]) && !skipobjects) {
params[param].forEach(function(item, ind) {
result += fromObject(item, false, c + "[" + ind + "]");
});
} else {
result += c + "=" + encodeURIComponent(params[param]) + "&";
}
}
return result;
};


var data = {
users: [{
"name": "jeff",
"tasks": [
"Do one thing",
"Do second thing"
]
},
{
"name": "rick",
"tasks": [
"Never gonna give you up",
"Never gonna let you down"
]
}
]
}


document.write(fromObject(data));

Best solution for Vanilla JavaScript:

var params = Object.keys(data)
.filter(function (key) {
return data[key] ? true : false
})
.map(function (key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(data[key])
})
.join('&');

PS: The filter is used here to remove null or undefined parameters. It makes the url look cleaner.

Make a utility if you have nodejs

const querystring = require('querystring')


export function makeQueryString(params): string {
return querystring.stringify(params)
}

import example

import { makeQueryString } from '~/utils'

example of use

  makeQueryString({
...query,
page
})

As most of the answers only convert flat objects to query parameters, I would like to share mine.

This function can handle flat objects, as well as nested arrays/objects while only using plain JS.

        function incapsulateInBrackets(key)
{
return '[' + key + ']';
}


function encode(object, isSubEncode=false, prefix = '')
{
let parts = Object.keys(object).map( (key) => {


let encodedParts = [];


if(Array.isArray(object[key]))
{
object[key].map(function(innerKey, index){


encodedParts.push( encode(object[key][index], true, prefix + key + incapsulateInBrackets(index)));


});
}
else if(object[key] instanceof Object)
{
Object.keys(object[key]).map( (innerKey) => {


if(Array.isArray(object[key][innerKey]))
{
encodedParts.push( encode(object[key][index], true, prefix + incapsulateInBrackets(key) + incapsulateInBrackets(innerKey)) );
}
else
{
encodedParts.push( prefix + incapsulateInBrackets(key) + incapsulateInBrackets(innerKey) + '=' +  object[key][innerKey] );
}


});
}
else
{
if(isSubEncode)
{
encodedParts.push( prefix + incapsulateInBrackets(key) + '=' + object[key] );
}
else
{
encodedParts.push( key + '=' + object[key] );
}
}


return encodedParts.join('&');


});


return parts.join('&');
}

The conversion from a JSON string to a URL query string can be done in a single line:

const json = '{"action":"actualiza_resultado","postID":1,"gl":2,"gl2":3}';
const queryString = new URLSearchParams(JSON.parse(json)).toString();

queryString would then be set to "action=actualiza_resultado&postID=1&gl=2&gl2=3".