是否有一个快速和简单的方法来编码JavaScript对象到字符串,我可以通过GET请求传递?

没有jQuery,没有其他框架-只有纯JavaScript:)


当前回答

URLSearchParams看起来不错,但是对于嵌套对象来说行不通。

试着使用

encodeURIComponent(JSON.stringify(object))

其他回答

jQuery有一个函数jQuery.param()。如果你已经在使用它,你可以使用这个:

例子:

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

STR现在包含宽度=1680&高度=1050。

如果有很多嵌套对象,前面的答案就不起作用了。

相反,你可以从jquery-param/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, '+');
};

在讨论了一些最重要的答案之后,我编写了另一个实现,它也可以处理一些边缘情况

function serialize(params, prefix) {                
    return Object.entries(params).reduce((acc, [key, value]) => {
        // remove whitespace from both sides of the key before encoding
        key = encodeURIComponent(key.trim());

        if (params.constructor === Array ) {
          key = `${prefix}[]`;
        } else if (params.constructor === Object) {
          key = (prefix ? `${prefix}[${key}]` : key);
        }

        /**
         *  - undefined and NaN values will be skipped automatically
         *  - value will be empty string for functions and null
         *  - nested arrays will be flattened
         */
        if (value === null || typeof value === 'function') {
            acc.push(`${key}=`);
        } else if (typeof value === 'object') {
            acc = acc.concat(serialize(value, key));
        } else if(['number', 'boolean', 'string'].includes(typeof value) && value === value) { // self-check to avoid NaN
            acc.push(`${key}=${encodeURIComponent(value)}`);
        }

        return acc;
    }, []);
}

function objectToQueryString(queryParameters) {
    return queryParameters ? serialize(queryParameters).join('&'): '';
}

let x = objectToQueryString({
    foo: 'hello world',
    bar: {
      blah: 123,
      list: [1, 2, 3],
        'nested array': [[4,5],[6,7]] // will be flattened
    },
    page: 1,
    limit: undefined, // field will be ignored
    check: false,
    max: NaN, // field will be ignored
    prop: null,
    ' key value': 'with spaces' // space in key will be trimmed out
});
  
console.log(x); // foo=hello%20world&bar[blah]=123&bar[list][]=1&bar[list][]=2&bar[list][]=3&bar[nested%20array][][]=4&bar[nested%20array][][]=5&bar[nested%20array][][]=6&bar[nested%20array][][]=7&page=1&check=false&prop=&key%20value=with%20spaces

URLSearchParams看起来不错,但是对于嵌套对象来说行不通。

试着使用

encodeURIComponent(JSON.stringify(object))

ES6解决方案用于JavaScript对象的查询字符串编码

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 (params)

"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"