代码之家  ›  专栏  ›  技术社区  ›  napolux

javascript对象的查询字符串编码

  •  390
  • napolux  · 技术社区  · 16 年前

    你知道一个快速简单的方法将一个javascript对象编码成 string 我可以通过 GET 请求?

    不 jQuery ,没有其他框架-只是简单的javascript:)

    32 回复  |  直到 7 年前
        1
  •  701
  •   Casper    8 年前

    这样地?

    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
        2
  •  215
  •   pau.moreno    9 年前

    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

        3
  •  114
  •   Mogsdad    12 年前
    Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
    

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

    function serialize( obj ) {
      return '?'+Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
    }
    
        4
  •  94
  •   Nico Tejera    10 年前

    这是ES6中的一行:

    Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
    
        5
  •  39
  •   Lucas Constantino Silva    10 年前

    使用node.js 6.6.3

    const querystring = require('querystring')
    
    const obj = {
      foo: 'bar',
      baz: 'tor'
    }
    
    let result = querystring.stringify(obj)
    // foo=bar&baz=tor
    

    参考文献: https://nodejs.org/api/querystring.html

        6
  •  28
  •   bmaggi    9 年前

    我建议使用 URLSearchParams 接口:

    const searchParams = new URLSearchParams();
    const search = {foo: "hi there", bar: "100%" };
    Object.keys(search).forEach(key => searchParams.append(key, search[key]));
    console.log(searchParams.toString())
    
        7
  •  23
  •   jssebastian    13 年前

    用户187291对公认解决方案的小修改:

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

    检查对象上的hasownProperty使jslin/jshint很高兴,如果对象不是简单的字典,它可以防止意外地序列化对象或其他东西的方法。有关本页中的声明,请参阅上的段落: http://javascript.crockford.com/code.html

        8
  •  14
  •   stephen.hanson    7 年前

    你能用吗? URLSearchParams ?

    只是 new URLSearchParams(object).toString()

    但铬49+。

        9
  •  10
  •   Tim Down    16 年前

    是否需要发送任意对象?如果是这样,GET是一个坏主意,因为用户代理和Web服务器将接受的URL长度有限制。我的建议是建立一个要发送的名称-值对数组,然后建立一个查询字符串:

    function QueryStringBuilder() {
        var nameValues = [];
    
        this.add = function(name, value) {
            nameValues.push( {name: name, value: value} );
        };
    
        this.toQueryString = function() {
            var segments = [], nameValue;
            for (var i = 0, len = nameValues.length; i < len; i++) {
                nameValue = nameValues[i];
                segments[i] = encodeURIComponent(nameValue.name) + "=" + encodeURIComponent(nameValue.value);
            }
            return segments.join("&");
        };
    }
    
    var qsb = new QueryStringBuilder();
    qsb.add("veg", "cabbage");
    qsb.add("vegCount", "5");
    
    alert( qsb.toQueryString() );
    
        10
  •  10
  •   developer033    9 年前

    Rails/PHP样式的查询生成器

    此方法将javascript对象转换为 URI Query String . 还处理嵌套数组和对象(在 Rails / PHP 语法):

    function serializeQuery(params, prefix) {
      const query = Object.keys(params).map((key) => {
        const value  = params[key];
    
        if (params.constructor === Array)
          key = `${prefix}[]`;
        else if (params.constructor === Object)
          key = (prefix ? `${prefix}[${key}]` : key);
    
        if (typeof value === 'object')
          return serializeQuery(value, key);
        else
          return `${key}=${encodeURIComponent(value)}`;
      });
    
      return [].concat.apply([], query).join('&');
    }
    

    示例用法:

    let params = {
      a: 100,
      b: 'has spaces',
      c: [1, 2, 3],
      d: { x: 9, y: 8}
    }
    
    serializeQuery(params)
    // returns 'a=100&b=has%20spaces&c[]=1&c[]=2&c[]=3&d[x]=9&d[y]=8
    
        11
  •  9
  •   Community Mohan Dere    9 年前

    使用JSON。

    看一看 this question 关于如何实施的想法。

        12
  •  9
  •   alf    14 年前

    这是接受答案的咖啡说明版本。这可能会为某人节省时间。

    serialize = (obj, prefix) ->
      str = []
      for p, v of obj
        k = if prefix then prefix + "[" + p + "]" else p
        if typeof v == "object"
          str.push(serialize(v, k))
        else
          str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v))
    
      str.join("&")
    
        13
  •  8
  •   Nino Filiu    7 年前

    好吧,每个人似乎都把他的一句话放在这里,所以这里是我的:

    const encoded = Object.entries(obj).map((k, v) => `${k}=${encodeURIComponent(v)}`).join("&");
    
        14
  •  6
  •   mikebridge    9 年前

    这是一个简洁的递归版本 Object.entries . 它处理任意嵌套的数组,但不处理嵌套的对象。它还删除空元素:

    const format = (k,v) => v !== null ? `${k}=${encodeURIComponent(v)}` : ''
    
    const to_qs = (obj) => {
        return [].concat(...Object.entries(obj)
                           .map(([k,v]) => Array.isArray(v) 
                              ? v.map(arr => to_qs({[k]:arr})) 
                              : format(k,v)))
               .filter(x => x)
               .join('&');
    }
    

    例如。:

    let json = { 
        a: [1, 2, 3],
        b: [],              // omit b
        c: 1,
        d: "test&encoding", // uriencode
        e: [[4,5],[6,7]],   // flatten this
        f: null,            // omit nulls
        g: 0
    };
    
    let qs = to_qs(json)
    
    => "a=1&a=2&a=3&c=1&d=test%26encoding&e=4&e=5&e=6&e=7&g=0"
    
        15
  •  4
  •   Pavlo Sadovyi    8 年前

    在ES7中,您可以将其写在一行中:

    const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
    
        16
  •  4
  •   steadweb    8 年前

    我有一个更简单的解决方案,它不使用任何第三方库,并且已经很容易在任何具有“object.keys”的浏览器中使用(即所有现代浏览器+edge+ie):

    在ES5中

    function(a){
        if( typeof(a) !== 'object' ) 
            return '';
        return `?${Object.keys(a).map(k=>`${k}=${a[k]}`).join('&')}`;
    }
    

    在ES3中

    function(a){
        if( typeof(a) !== 'object' ) 
            return '';
        return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
    }
    
        17
  •  3
  •   Wytze    14 年前

    如果要递归地转换嵌套对象,而该对象可能包含或不包含数组(数组可能包含对象或数组等),则解决方案会变得更复杂一些。这是我的尝试。

    我还添加了一些选项来选择是否要记录每个对象成员在其所在的主对象中的深度,以及选择是否要向来自已转换数组的成员添加标签。

    理想情况下,您应该测试thing参数是否真的接收到对象或数组。

    function thingToString(thing,maxDepth,recordLevel,markArrays){
        //thing: object or array to be recursively serialized
        //maxDepth (int or false):
        // (int) how deep to go with converting objects/arrays within objs/arrays
        // (false) no limit to recursive objects/arrays within objects/arrays
        //recordLevel (boolean):
        //  true - insert "(level 1)" before transcript of members at level one (etc)
        //  false - just 
        //markArrays (boolean):
        //  insert text to indicate any members that came from arrays
        var result = "";
        if (maxDepth !== false && typeof maxDepth != 'number') {maxDepth = 3;}
        var runningDepth = 0;//Keeps track how deep we're into recursion
    
        //First prepare the function, so that it can call itself recursively
        function serializeAnything(thing){
            //Set path-finder values
            runningDepth += 1;
            if(recordLevel){result += "(level " + runningDepth + ")";}
    
            //First convert any arrays to object so they can be processed
            if (thing instanceof Array){
                var realObj = {};var key;
                if (markArrays) {realObj['type'] = "converted array";}
                for (var i = 0;i < thing.length;i++){
                    if (markArrays) {key = "a" + i;} else {key = i;}
                    realObj[key] = thing[i];
                }
                thing = realObj;
                console.log('converted one array to ' + typeof realObj);
                console.log(thing);
            }
    
            //Then deal with it
            for (var member in thing){
                if (typeof thing[member] == 'object' && runningDepth < maxDepth){
                    serializeAnything(thing[member]);
                    //When a sub-object/array is serialized, it will add one to
                    //running depth. But when we continue to this object/array's
                    //next sibling, the level must go back up by one
                    runningDepth -= 1;
                } else if (maxDepth !== false && runningDepth >= maxDepth) {
                    console.log('Reached bottom');
                } else 
                if (
                    typeof thing[member] == "string" || 
                    typeof thing[member] == 'boolean' ||
                    typeof thing[member] == 'number'
                ){
                    result += "(" + member + ": " + thing[member] + ") ";
                }  else {
                    result += "(" + member + ": [" + typeof thing[member] + " not supported]) ";
                }
            }
        }
        //Actually kick off the serialization
        serializeAnything(thing);
    
        return result;
    
    }
    
        18
  •  3
  •   A.Aziem Moemen    10 年前

    除了可接受的解决方案之外,它还适用于对象和对象数组:

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

    如果您正在使用对象参数(如在ASP.NET MVC操作方法中),那么还添加了objname。

        19
  •  3
  •   Community Mohan Dere    9 年前

    稍微好看一点

    objectToQueryString(obj, prefix) {
        return Object.keys(obj).map(objKey => {
            if (obj.hasOwnProperty(objKey)) {
                const key = prefix ? `${prefix}[${objKey}]` : objKey;
                const value = obj[objKey];
    
                return typeof value === "object" ?
                    this.objectToQueryString(value, key) :
                    `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
            }
    
            return null;
        }).join("&");
    }
    
        20
  •  3
  •   nimatra    9 年前

    这个跳过空/未定义的值

    export function urlEncodeQueryParams(data) {
        const params = Object.keys(data).map(key => data[key] ? `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}` : '');
        return params.filter(value => !!value).join('&');
    }
    
        21
  •  3
  •   Laravel Plus    8 年前

    单行将对象转换为查询字符串,以防有人再次需要它。

    let Objs = { a: 'obejct-a', b: 'object-b' }
    
    Object.keys(objs).map(key => key + '=' + objs[key]).join('&')
    
    // result will be a=object-a&b=object-b
    
        22
  •  3
  •   niutech    8 年前

    我做了一个 comparison of JSON stringifiers 结果如下:

    JSON:    {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":"$1,446.35","age":32,"name":"Logan Keller","email":"logankeller@artiq.com","phone":"+1 (952) 533-2258","friends":[{"id":0,"name":"Colon Salazar"},{"id":1,"name":"French Mcneil"},{"id":2,"name":"Carol Martin"}],"favoriteFruit":"banana"}
    Rison:   (_id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258')
    O-Rison: _id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258'
    JSURL:   ~(_id~'5973782bdb9a930533b05cb2~isActive~true~balance~'!1*2c446.35~age~32~name~'Logan*20Keller~email~'logankeller*40artiq.com~phone~'*2b1*20*28952*29*20533-2258~friends~(~(id~0~name~'Colon*20Salazar)~(id~1~name~'French*20Mcneil)~(id~2~name~'Carol*20Martin))~favoriteFruit~'banana)
    QS:      _id=5973782bdb9a930533b05cb2&isActive=true&balance=$1,446.35&age=32&name=Logan Keller&email=logankeller@artiq.com&phone=+1 (952) 533-2258&friends[0][id]=0&friends[0][name]=Colon Salazar&friends[1][id]=1&friends[1][name]=French Mcneil&friends[2][id]=2&friends[2][name]=Carol Martin&favoriteFruit=banana
    URLON:   $_id=5973782bdb9a930533b05cb2&isActive:true&balance=$1,446.35&age:32&name=Logan%20Keller&email=logankeller@artiq.com&phone=+1%20(952)%20533-2258&friends@$id:0&name=Colon%20Salazar;&$id:1&name=French%20Mcneil;&$id:2&name=Carol%20Martin;;&favoriteFruit=banana
    QS-JSON: isActive=true&balance=%241%2C446.35&age=32&name=Logan+Keller&email=logankeller%40artiq.com&phone=%2B1+(952)+533-2258&friends(0).id=0&friends(0).name=Colon+Salazar&friends(1).id=1&friends(1).name=French+Mcneil&friends(2).id=2&friends(2).name=Carol+Martin&favoriteFruit=banana
    

    其中最短的是 URL Object Notation .

        23
  •  2
  •   hayatoShingu    13 年前

    好吧,这是一篇老文章,但我正面临这个问题,我已经找到了我的个人解决方案。也许可以帮助别人……

         function objToQueryString(obj){
            var k = Object.keys(obj);
            var s = "";
            for(var i=0;i<k.length;i++) {
                s += k[i] + "=" + encodeURIComponent(obj[k[i]]);
                if (i != k.length -1) s += "&";
            }
            return s;
         };
    
        24
  •  2
  •   Vandana Sharma    9 年前

    如果您有很多嵌套对象,上面的答案将不起作用。 相反,您可以从这里选择函数参数- https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js 对我来说效果很好!

        var param = function (a) {
        var s = [], rbracket = /\[\]$/,
            isArray = function (obj) {
                return Object.prototype.toString.call(obj) === '[object Array]';
            }, add = function (k, v) {
                v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v;
                s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
            }, buildParams = function (prefix, obj) {
                var i, len, key;
    
                if (prefix) {
                    if (isArray(obj)) {
                        for (i = 0, len = obj.length; i < len; i++) {
                            if (rbracket.test(prefix)) {
                                add(prefix, obj[i]);
                            } else {
                                buildParams(prefix + '[' + (typeof obj[i] === 'object' ? i : '') + ']', obj[i]);
                            }
                        }
                    } else if (obj && String(obj) === '[object Object]') {
                        for (key in obj) {
                            buildParams(prefix + '[' + key + ']', obj[key]);
                        }
                    } else {
                        add(prefix, obj);
                    }
                } else if (isArray(obj)) {
                    for (i = 0, len = obj.length; i < len; i++) {
                        add(obj[i].name, obj[i].value);
                    }
                } else {
                    for (key in obj) {
                        buildParams(key, obj[key]);
                    }
                }
                return s;
            };
    
        return buildParams('', a).join('&').replace(/%20/g, '+');
    };
    
        25
  •  2
  •   Angel Venchev    7 年前

    这是一个现成的.NET后端解决方案。我已经获得了这个线程的主要答案,并根据我们的.NET需求对其进行了更新。

    function objectToQuerystring(params) {
    var result = '';
    
        function convertJsonToQueryString(data, progress, name) {
            name = name || '';
            progress = progress || '';
            if (typeof data === 'object') {
                Object.keys(data).forEach(function (key) {
                    var value = data[key];
                    if (name == '') {
                        convertJsonToQueryString(value, progress, key);
                    } else {
                        if (isNaN(parseInt(key))) {
                            convertJsonToQueryString(value, progress, name + '.' + key);
                        } else {
                            convertJsonToQueryString(value, progress, name + '[' + key+ ']');
                        }
                    }
                })
            } else {
                result = result ? result.concat('&') : result.concat('?');
                result = result.concat(`${name}=${data}`);
            }
        }
    
        convertJsonToQueryString(params);
        return result;
    }
    
        26
  •  1
  •   gandharv garg    7 年前

    一个javascript对象的查询字符串编码的ES6解决方案

    const params = {
      a: 1,
      b: 'query stringify',
      c: null,
      d: undefined,
      f: '',
      g: { foo: 1, bar: 2 },
      h: ['Winterfell', 'Westeros', 'Braavos'],
      i: { first: { second: { third: 3 }}}
    }
    
    static toQueryString(params = {}, prefix) {
      const query = Object.keys(params).map((k) => {
        let key = k;
        const value = params[key];
    
        if (!value && (value === null || value === undefined || isNaN(value))) {
          value = '';
        }
    
        switch (params.constructor) {
          case Array:
            key = `${prefix}[]`;
            break;
          case Object:
            key = (prefix ? `${prefix}[${key}]` : key);
            break;
        }
    
        if (typeof value === 'object') {
          return this.toQueryString(value, key); // for nested objects
        }
    
        return `${key}=${encodeURIComponent(value)}`;
      });
    
      return query.join('&');
    }
    

    ToQueryString(参数)

    "a=1&b=query%20stringify&c=&d=&f=&g[foo]=1&g[bar]=2&h[]=Winterfell&h[]=Westeros&h[]=Braavos&i[first][second][third]=3"
    
        27
  •  0
  •   Marco Demaio    13 年前

    另一种方法(无递归对象):

       getQueryString = function(obj)
       {
          result = "";
    
          for(param in obj)
             result += ( encodeURIComponent(param) + '=' + encodeURIComponent(obj[param]) + '&' );
    
          if(result) //it's not empty string when at least one key/value pair was added. In such case we need to remove the last '&' char
             result = result.substr(0, result.length - 1); //If length is zero or negative, substr returns an empty string [ref. http://msdn.microsoft.com/en-us/library/0esxc5wy(v=VS.85).aspx]
    
          return result;
       }
    
    alert( getQueryString({foo: "hi there", bar: 123, quux: 2 }) );
    
        28
  •  0
  •   Long Ranger    9 年前

    请参阅答案@user187291,添加“isarray”作为参数,使JSON嵌套数组转换。

    data : {
                        staffId : "00000001",
                        Detail : [ {
                            "identityId" : "123456"
                        }, {
                            "identityId" : "654321"
                        } ],
    
                    }
    

    要得到结果:

    staffid=0000000 1&detail[0].标识id=123456&detail[1].标识id=654321

    serialize = function(obj, prefix, isArray) {
            var str = [],p = 0;
            for (p in obj) {
                if (obj.hasOwnProperty(p)) {
                    var k, v;
                    if (isArray)
                        k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
                    else
                        k = prefix ? prefix + "." + p + "" : p, v = obj[p];
    
                    if (v !== null && typeof v === "object") {
                        if (Array.isArray(v)) {
                            serialize(v, k, true);
                        } else {
                            serialize(v, k, false);
                        }
                    } else {
                        var query = k + "=" + v;
                        str.push(query);
                    }
                }
            }
            return str.join("&");
        };
    
        serialize(data, "prefix", false);
    
        29
  •  0
  •   Nikhil Mahirrao    8 年前

    您也可以通过使用简单的 JavaScript .

    const stringData = '?name=Nikhil&surname=Mahirrao&age=30';
        
    const newData= {};
    stringData.replace('?', '').split('&').map((value) => {
      const temp = value.split('=');
      newData[temp[0]] = temp[1];
    });
    
    console.log('stringData: '+stringData);
    console.log('newData: ');
    console.log(newData);
        30
  •  0
  •   Anthony Zhan    8 年前

    const buildSortedQuery = (args) => {
        return Object.keys(args)
            .sort()
            .map(key => {
                return window.encodeURIComponent(key)
                    + '='
                    + window.encodeURIComponent(args[key]);
            })
            .join('&');
    };
    
    console.log(buildSortedQuery({
      foo: "hi there",
      bar: "100%"
    }));
    
    //bar=100%25&foo=hi%20there