Javascript 对象的查询字符串编码

IT技术 javascript query-string urlencode
2021-01-10 08:41:16

您知道一种将 Javascript 对象编码为string可以通过GET请求传递的快速而简单的方法吗?

jQuery,没有其他框架 - 只是普通的 Javascript :)

6个回答

像这样?

serialize = function(obj) {
  var str = [];
  for (var p in obj)
    if (obj.hasOwnProperty(p)) {
      str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
    }
  return str.join("&");
}

console.log(serialize({
  foo: "hi there",
  bar: "100%"
}));
// foo=hi%20there&bar=100%25

编辑:这个也转换递归对象(使用php“array”表示法作为查询字符串)

serialize = function(obj, prefix) {
  var str = [],
    p;
  for (p in obj) {
    if (obj.hasOwnProperty(p)) {
      var k = prefix ? prefix + "[" + p + "]" : p,
        v = obj[p];
      str.push((v !== null && typeof v === "object") ?
        serialize(v, k) :
        encodeURIComponent(k) + "=" + encodeURIComponent(v));
    }
  }
  return str.join("&");
}

console.log(serialize({
  foo: "hi there",
  bar: {
    blah: 123,
    quux: [1, 2, 3]
  }
}));
// foo=hi%20there&bar%5Bblah%5D=123&bar%5Bquux%5D%5B0%5D=1&bar%5Bquux%5D%5B1%5D=2&bar%5Bquux%5D%5B2%5D=3

它不会打破 {foo: [1,2,3], bar: "100%" } 吗?
2021-03-13 08:41:16
@TimDown 关于您在 GET 请求中发送简单参数的评论。我不同意。将参数分组到数组中可能会变得很方便,因为服务器端的 PHP 找到了一个准备就绪的关联数组。我不明白为什么这是错误的设计。
2021-03-15 08:41:16
'if (obj.hasOwnProperty(prop))' 是否必要?for in 语句循环刚好在对象的属性上,因此调用 hasOwnProperty 总是评估为 true
2021-03-16 08:41:16
@Marcel 那是因为该函数不检查 hasOwnProperty。我已经更新了你的小提琴,现在它更新了:jsfiddle.net/rudiedirkx/U5Tyb/1
2021-03-18 08:41:16
@Ofri:对于设置为接收它的服务器的 POST 请求,JSON 是一个不错的选择。对于 GET 请求,如果您向服务器发送的不是一些简单的参数,那么您的设计很可能是错误的。
2021-04-04 08:41:16

只需使用URLSearchParams适用于所有当前浏览器

new URLSearchParams(object).toString()
@EddieMongeJr 甚至接受的答案(和其他人简单地看一下)也不支持嵌套对象。您可以stringify先嵌套对象URLSearchParams
2021-03-11 08:41:16
@EddieMongeJr 查询字符串按设计是键值对,您甚至不应该序列化嵌套对象这个答案是现代方法。需要点赞。
2021-03-26 08:41:16
不适用于嵌套对象。 let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
2021-03-29 08:41:16
不,因为它不做递归对象
2021-04-02 08:41:16
是的,它们是键值对,但没有说明该值不能是字符串编码对象。此外,原始问题要求“将 Javascript 对象转换为字符串”,它可以具有嵌套属性
2021-04-05 08:41:16

jQuery 有一个功能jQuery.param(),如果你已经在使用它,你可以使用它:http : //api.jquery.com/jquery.param/

例子:

var params = { width:1680, height:1050 };
var str = jQuery.param( params );

str 现在包含 width=1680&height=1050

引用 Napolux(OP):“只是普通的 Javascript”:P
2021-03-21 08:41:16
@akond jQuery 文档特别指出,您不能传入裸数组。
2021-03-21 08:41:16
@Ariel 他没有传入一个裸数组。他传入一个在索引 2564 处只有一个值的数组为了演示: var a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); 结果在"parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo". 虽然正确,但可能不是您所期望的。
2021-03-21 08:41:16
问题有专门问过Vanilla JS
2021-03-30 08:41:16
jQuery.param() 有险恶的行为。尝试执行 var a = []; [2564] = 12; console.log(jQuery.param({ propertylist: a })); 看看我的意思。
2021-03-31 08:41:16

我建议使用URLSearchParams接口:

const searchParams = new URLSearchParams();
const params = {foo: "hi there", bar: "100%" };
Object.keys(params).forEach(key => searchParams.append(key, params[key]));
console.log(searchParams.toString())

或者通过将搜索对象传递给构造函数,如下所示:

const params = {foo: "hi there", bar: "100%" };
const queryString = new URLSearchParams(params).toString();
console.log(queryString);

请注意,如今,在现代环境中,Object.entries如果您的起点是上述对象,则可以使用const searchParams = new URLSearchParams(Object.entries(params));
2021-03-29 08:41:16
如果你不打算支持 IE(现在很常见)和一些特定的移动版本,这是最好的答案,因为它是纯 JavaScript。
2021-04-03 08:41:16
@bravemaster 这是一个很好的解决方案,尤其是对于节点开发人员。谢谢!
2021-04-04 08:41:16
有趣的建议,但请注意浏览器对此功能的支持仍然非常不完整。
2021-04-06 08:41:16
@bmaggi 不适用于嵌套属性 {a: { 1: 'test', 2: 'test2'}} 预期: a[1]=test&a[2]=test2
2021-04-07 08:41:16
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

编辑:我喜欢这个单行,但我敢打赌,如果它在语义上与接受的答案相匹配,那将是一个更受欢迎的答案:

function serialize( obj ) {
    let str = '?' + Object.keys(obj).reduce(function(a, k){
        a.push(k + '=' + encodeURIComponent(obj[k]));
        return a;
    }, []).join('&');
    return str;
}
如果您使用的术语比serialize编辑的函数名称更不通用,那么这个答案会更受欢迎,也许encodeAsQueryString. 否则,每个人都必须为实际使用重命名它——或者更糟的是,不要重命名它。
2021-03-13 08:41:16
但是,reduce 功能的专用行将大大提高可读性。
2021-03-23 08:41:16
使用 ES6 模板而不是串联进一步改进了 @Jannes 代码 - Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
2021-03-25 08:41:16
请注意,Object.keys仅在 IE >= 9 中可用
2021-03-30 08:41:16
使用 .map() 而不是 .reduce() 会更简单: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
2021-04-02 08:41:16