美元的。在JavaScript / jQuery中,param()反函数。

时间:2022-04-17 22:01:12

Given the following form:

鉴于以下形式:

<form>
    <input name="foo" value="bar">
    <input name="hello" value="hello world">
</form>

I can use the $.param( .. ) construct to serialize the form:

我可以用美元。参数(. .)构建以序列化形式:

$.param( $('form input') )

=> foo=bar&hello=hello+world

How can I deserialize the above String with JavaScript and get a hash back?

如何用JavaScript反序列化上面的字符串,然后返回一个散列?

For example,

例如,

$.magicFunction("foo=bar&hello=hello+world")

=> {'foo' : 'bar', 'hello' : 'hello world'}

Reference: jQuery.param( obj ).

参考:jQuery。参数(obj)。

15 个解决方案

#1


56  

You should use jQuery BBQ's deparam function. It's well-tested and documented.

您应该使用jQuery BBQ的deparam函数。它是经过良好测试的和记录。

#2


28  

This is a slightly modified version of a function I wrote a while ago to do something similar.

这是一个稍微修改过的函数,我之前写过类似的东西。

var QueryStringToHash = function QueryStringToHash  (query) {
  var query_string = {};
  var vars = query.split("&");
  for (var i=0;i<vars.length;i++) {
    var pair = vars[i].split("=");
    pair[0] = decodeURIComponent(pair[0]);
    pair[1] = decodeURIComponent(pair[1]);
        // If first entry with this name
    if (typeof query_string[pair[0]] === "undefined") {
      query_string[pair[0]] = pair[1];
        // If second entry with this name
    } else if (typeof query_string[pair[0]] === "string") {
      var arr = [ query_string[pair[0]], pair[1] ];
      query_string[pair[0]] = arr;
        // If third or later entry with this name
    } else {
      query_string[pair[0]].push(pair[1]);
    }
  } 
  return query_string;
};

#3


16  

How about this short functional approach?

那么这个简短的函数方法呢?

function parseParams(str) {
    return str.split('&').reduce(function (params, param) {
        var paramSplit = param.split('=').map(function (value) {
            return decodeURIComponent(value.replace(/\+/g, ' '));
        });
        params[paramSplit[0]] = paramSplit[1];
        return params;
    }, {});
}

Example:

例子:

parseParams("this=is&just=an&example") // Object {this: "is", just: "an", example: undefined}

#4


13  

My answer:

我的回答:

function(query){
  var setValue = function(root, path, value){
    if(path.length > 1){
      var dir = path.shift();
      if( typeof root[dir] == 'undefined' ){
        root[dir] = path[0] == '' ? [] : {};
      }

      arguments.callee(root[dir], path, value);
    }else{
      if( root instanceof Array ){
        root.push(value);
      }else{
        root[path] = value;
      }
    }
  };
  var nvp = query.split('&');
  var data = {};
  for( var i = 0 ; i < nvp.length ; i++ ){
    var pair = nvp[i].split('=');
    var name = decodeURIComponent(pair[0]);
    var value = decodeURIComponent(pair[1]);

    var path = name.match(/(^[^\[]+)(\[.*\]$)?/);
    var first = path[1];
    if(path[2]){
      //case of 'array[level1]' || 'array[level1][level2]'
      path = path[2].match(/(?=\[(.*)\]$)/)[1].split('][')
    }else{
      //case of 'name'
      path = [];
    }
    path.unshift(first);

    setValue(data, path, value);
  }
  return data;
}

#5


9  

I am using David Dorward's answer, and realized that it doesn't behave like PHP or Ruby on Rails how they parse the params:

我正在使用David Dorward的回答,并意识到它不像PHP或Ruby on Rails那样,如何解析params:

1) a variable is only an array if it ends with [], such as ?choice[]=1&choice[]=12, not when it is ?a=1&a=2

1)一个变量仅是一个数组,如果它以[],比如?choice[]=1&choice[]=12,而不是当它是?a=1&a=2。

2) when mulitple params exist with the same name, the later ones replaces the earlier ones, as on PHP servers (Ruby on Rails keep the first one and ignore the later ones), such as ?a=1&b=2&a=3

当mulitple params以相同的名称存在时,后面的函数将替换前面的那些,如PHP服务器(Ruby on Rails保留第一个,忽略后面的),例如?a=1&b=2&a=3。

So modifying David's version, I have:

所以修改大卫的版本,我有:

function QueryStringToHash(query) {

  if (query == '') return null;

  var hash = {};

  var vars = query.split("&");

  for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split("=");
    var k = decodeURIComponent(pair[0]);
    var v = decodeURIComponent(pair[1]);

    // If it is the first entry with this name
    if (typeof hash[k] === "undefined") {

      if (k.substr(k.length-2) != '[]')  // not end with []. cannot use negative index as IE doesn't understand it
        hash[k] = v;
      else
        hash[k.substr(0, k.length-2)] = [v];

    // If subsequent entry with this name and not array
    } else if (typeof hash[k] === "string") {
      hash[k] = v;  // replace it

    // If subsequent entry with this name and is array
    } else {
      hash[k.substr(0, k.length-2)].push(v);
    }
  } 
  return hash;
};

which is tested fairly thoroughly.

这是相当彻底的测试。

#6


6  

Here's how you could create a new jQuery function:

下面是如何创建一个新的jQuery函数:

jQuery.unparam = function (value) {
    var
    // Object that holds names => values.
    params = {},
    // Get query string pieces (separated by &)
    pieces = value.split('&'),
    // Temporary variables used in loop.
    pair, i, l;

    // Loop through query string pieces and assign params.
    for (i = 0, l = pieces.length; i < l; i++) {
        pair = pieces[i].split('=', 2);
        // Repeated parameters with the same name are overwritten. Parameters
        // with no value get set to boolean true.
        params[decodeURIComponent(pair[0])] = (pair.length == 2 ?
            decodeURIComponent(pair[1].replace(/\+/g, ' ')) : true);
    }

    return params;
};

#7


6  

Thanks to him http://james.padolsey.com/javascript/parsing-urls-with-the-dom/

由于他http://james.padolsey.com/javascript/parsing-urls-with-the-dom/

Pretty easy :D

很简单:D

function params_unserialize(p){
var ret = {},
    seg = p.replace(/^\?/,'').split('&'),
    len = seg.length, i = 0, s;
for (;i<len;i++) {
    if (!seg[i]) { continue; }
    s = seg[i].split('=');
    ret[s[0]] = s[1];
}
return ret;}

#8


6  

I know this is an old thread, but maybe there is still some relevance in it?

我知道这是一个古老的线索,但也许它仍然有关联?

Inspired by Jacky Li's good solution I tried a slight variation of my own with the objective to also be able to take care of arbitrary combinations of arrays and objects as input. I looked at how PHP would have done it and tried to get something "similar" going. Here is my code:

在Jacky Li的良好解决方案的启发下,我尝试了自己的一个微小的变化,目标也可以处理任意组合的数组和对象作为输入。我查看了PHP是如何做到的,并试图得到类似的结果。这是我的代码:

function getargs(str){
   var ret={};
   function build(urlnam,urlval,obj){ // extend the return object ...
    var i,k,o=obj, x, rx=/\[([^\]]*)\]/g, idx=[urlnam.replace(rx,'')];
    while (x=rx.exec(urlnam)) idx.push(x[1]); 
    while(true){
     k=idx.shift();
     if(k.trim()=='') {// key is empty: autoincremented index
       if (o.constructor.name=='Array') k=o.length; // for Array
       else if (o===obj ) {k=null}  // for first level property name
       else {k=-1;                                  // for Object
         for(i in o) if (+i>k) k=+i;
         k++;
       }
     }
     if(idx.length) { 
       // set up an array if the next key (idx[0]) appears to be
       // numeric or empty, otherwise set up an object:
       if (o[k]==null || typeof o[k]!='object') o[k]=isNaN(idx[0])?{}:[]; 
       o=o[k]; // move on to the next level
     }
     else { // OK, time to store the urlval in its chosen place ...
       // console.log('key',k,'val',urlval);                 
       o[k]=urlval===""?null:urlval; break; // ... and leave the while loop.
     } 
    }
    return obj;
   }
   // ncnvt: is a flag that governs the conversion of
   // numeric strings into numbers
   var ncnvt=true,i,k,p,v,argarr=[],
       ar=(str||window.location.search.substring(1)).split("&"),
       l=ar.length;
   for (i=0;i<l;i++) {if (ar[i]==="") continue;
     p=ar[i].split("=");k=decodeURIComponent(p[0]);
     v=p[1];v=(v!=null)?decodeURIComponent(v.replace(/\+/g,'%20')):'';
     if (ncnvt && v.trim()>"" && !isNaN(v)) v-=0;
     argarr.push([k,v]);  // array: key-value-pairs of all arguments
   }
   for (i=0,l=argarr.length;i<l;i++) build(argarr[i][0],argarr[i][1],ret);
   return ret;
}

If the function is called without the str-argument it will assume window.location.search.slice(1) as input.

如果函数在没有字符串参数的情况下被调用,它将假设window.location.search.slice(1)作为输入。

Some examples:

一些例子:

['a=1&a=2',                               // 1
 'x[y][0][z][]=1',                        // 2
 'hello=[%22world%22]&world=hello',       // 3
 'a=1&a=2&&b&c=3&d=&=e&',                 // 4
 'fld[2][]=2&fld[][]=3&fld[3][]=4&fld[]=bb&fld[]=cc',  // 5
 $.param({a:[[1,2],[3,4],{aa:'one',bb:'two'},[5,6]]}), // 6
 'a[]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13',// 7
 'a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13'// 8
].map(function(v){return JSON.stringify(getargs(v));}).join('\n')

results in

结果

{"a":2}                                    // 1
{"x":{"y":[{"z":[1]}]}}                    // 2
{"hello":"[\"world\"]","world":"hello"}    // 3
{"a":2,"b":null,"c":3,"d":null,"null":"e"} // 4 = { a: 2, b: null, c: 3, d: null, null: "e" }
{"fld":[null,null,[2],[3,4],"bb","cc"]}    // 5 
{"a":[[1,2],[3,4],{"aa":"one","bb":"two"},[5,6]]}  // 6
{"a":["hi",2,null,[7,99],13]}              // 7
{"a":{"0":2,"3":[7,99],"4":13,"x":"hi"}}   // 8

Whereas Jacky Li's solution would produce the outer container for a as a plain object

而Jacky Li的解决方案则是将a作为一个普通对象生成外部容器。

{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output

getargs() looks at the first given index for any level to determine whether this level will be an object (non-numeric index) or an array (numeric or empty), thus resulting in the output as shown in the listing bove (no. 6).

getargs()查看任何级别的第一个给定索引,以确定该级别是否为对象(非数字索引)或数组(数字或空),从而导致输出如清单bove所示(不)。6)。

If the current object is an array then nulls get inserted wherever necessary to represent empty positions. Arrays are always consecutively numbered and 0-based).

如果当前对象是一个数组,则在必要时插入null,以表示空位置。数组总是连续编号和基于0的。

Note, that in the example no. 8 the "autoincrement" for empty indices still works, even though we are dealing with an object now and not an array.

注意,在例子中没有。空索引的“自动增量”仍然有效,尽管我们现在处理的是对象而不是数组。

As far as I have tested it, my getargs() behaves pretty much identically to Chriss Roger's great jQuery $.deparam() plugin mentioned in the accepted answer. The main difference is that getargs runs without jQuery and that it does autoincrement in objects while $.deparam() will not do that:

在我测试过的情况下,我的getargs()行为几乎完全相同于Chriss Roger的jQuery $.deparam()插件。主要的区别是getargs没有jQuery,它在对象中自动递增,而$.deparam()不会这样做:

JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);

results in

结果

{"3":["7","99"],"x":"hi","undefined":"13"}

In $.deparam() the index [] is interpreted as an undefined instead of an autoincremented numerical index.

在$.deparam()中,索引[]被解释为一个未定义的,而不是一个自动递增的数值索引。

#9


3  

Here's my JavaScript implementation which I use in a server-side JScript ASP Classic page (demo):

下面是我在服务器端JScript ASP经典页面(demo)中使用的JavaScript实现:

// Transforms a query string in the form x[y][0][z][]=1 into {x:{y:[{z:[1]}]}}
function parseJQueryParams(p) {
    var params = {};
    var pairs = p.split('&');
    for (var i=0; i<pairs.length; i++) {
        var pair = pairs[i].split('=');
        var indices = [];
        var name = decodeURIComponent(pair[0]),
            value = decodeURIComponent(pair[1]);

        var name = name.replace(/\[([^\]]*)\]/g, 
            function(k, idx) { indices.push(idx); return ""; });

        indices.unshift(name);
        var o = params;

        for (var j=0; j<indices.length-1; j++) {
            var idx = indices[j];
            var nextIdx = indices[j+1];
            if (!o[idx]) {
                if ((nextIdx == "") || (/^[0-9]+$/.test(nextIdx)))
                    o[idx] = [];
                else
                    o[idx] = {};
            }
            o = o[idx];
        }

        idx = indices[indices.length-1];
        if (idx == "") {
            o.push(value);
        }
        else {
            o[idx] = value;
        }
    }
    return params;
}

#10


0  

This is my version in Coffeescript. Also works for url like http://localhost:4567/index.html?hello=[%22world%22]&world=hello#/home

这是我在Coffeescript的版本。也适用于url,例如http://localhost:4567/index.html?hello=[%22 %22]&world=hello#/home。

getQueryString: (url)->
    return null if typeof url isnt 'string' or url.indexOf("http") is -1

    split = url.split "?"

    return null if split.length < 2 
    path = split[1]

    hash_pos = path.indexOf "#"
    path = path[0...hash_pos] if hash_pos isnt -1

    data = path.split "&"
    ret = {}
    for d in data
      [name, val] = d.split "=" 
      name = decodeURIComponent name
      val = decodeURIComponent val
      try 
        ret[name] = JSON.parse val
      catch error
        ret[name] = val
    return ret

#11


0  

I came up with this solution, which behaves like the .Net function HttpUtility.ParseQueryString.

我提出了这个解决方案,它的行为像。net函数HttpUtility.ParseQueryString。

In the result, the query string parameters are store in properties as lists of values, so that qsObj["param"] will be the same as calling GetValues("param") in .Net.

在结果中,查询字符串参数作为值列表存储在属性中,因此qsObj[“param”]将与. net中调用GetValues(“param”)相同。

I hope you like it. JQuery not required.

我希望你喜欢。JQuery不是必需的。

var parseQueryString = function (querystring) {
    var qsObj = new Object();
    if (querystring) {
        var parts = querystring.replace(/\?/, "").split("&");
        var up = function (k, v) {
            var a = qsObj[k];
            if (typeof a == "undefined") {
                qsObj[k] = [v];
            }
            else if (a instanceof Array) {
                a.push(v);
            }
        };
        for (var i in parts) {
            var part = parts[i];
            var kv = part.split('=');
            if (kv.length == 1) {
                var v = decodeURIComponent(kv[0] || "");
                up(null, v);
            }
            else if (kv.length > 1) {
                var k = decodeURIComponent(kv[0] || "");
                var v = decodeURIComponent(kv[1] || "");
                up(k, v);
            }
        }
    }
    return qsObj;
};

Here is how to use it:

下面是如何使用它:

var qsObj = parseQueryString("a=1&a=2&&b&c=3&d=&=e&");

To preview the result in the console juste type in:

要在控制台中预览结果,请输入:

JSON.stringify(qsObj)

Output:

输出:

"{"a":["1","2"],"null":["","b",""],"c":["3"],"d":[""],"":["e"]}"

#12


0  

There's a beautiful one-liner over at CSS-Tricks (original source from Nicholas Ortenzio):

在css -把戏中有一个漂亮的俏皮话(来自尼古拉斯·奥登齐奥的原始资料):

function getQueryParameters(str) {
    return (str || document.location.search).replace(/(^\?)/,'').split("&").map(function(n){return n = n.split("="),this[n[0]] = n[1],this}.bind({}))[0];
}

The really clever part is how it uses the anonymous function's this object, adding a key/value pair for each of the queries in the string. That said, there's some room for improvement. I've modified it a bit below, with the following changes:

真正聪明的部分是它如何使用匿名函数的这个对象,在字符串中为每个查询添加一个键/值对。这就是说,还有一些改进的空间。我已经修改了下面的内容,下面的修改如下:

  1. Added handling of empty strings and non-string input.

    添加处理空字符串和非字符串输入。

  2. Handled URI-encoded strings (%40->@, etc).

    处理uri编码的字符串(%40->@,等等)。

  3. Removed the default use of document.location.search when the input was empty.

    删除document.location的默认使用。在输入为空时进行搜索。

  4. Changed the name, made it more readable, added comments.

    更改了名称,使其更具可读性,添加了注释。

function deparam(str) {
    // Uses an empty 'this' to build up the results internally
    function splitQuery(query) {
        query = query.split('=').map(decodeURIComponent);
        this[query[0]] = query[1];
        return this;
    }

    // Catch bad input
    if (!str || !(typeof str === 'string' || str instanceof String))
        return {};

    // Split the string, run splitQuery on each piece, and return 'this'
    var queries = str.replace(/(^\?)/,'').split('&');
    return queries.map(splitQuery.bind({}))[0];
}

#13


0  

Here's a simple & compact one if you only want to quickly get the parameters from a GET request:

如果您只想快速获得get请求中的参数,这里有一个简单紧凑的示例:

function httpGet() {
    var a={},b,i,q=location.search.replace(/^\?/,"").split(/\&/);
    for(i in q) if(q[i]) {b=q[i].split("=");if(b[0]) a[b[0]]=
    decodeURIComponent(b[1]).replace(/\+/g," ");} return a;
}

It converts

它转换

something?aa=1&bb=2&cc=3

into an object like

成一个对象

{aa:1,bb:2,cc:3}

#14


-1  

answers could use a bit of jQuery elegance:

答案可以用一点jQuery的优雅:

(function($) {
var re = /([^&=]+)=?([^&]*)/g;
var decodeRE = /\+/g; // Regex for replacing addition symbol with a space
var decode = function (str) {return decodeURIComponent( str.replace(decodeRE, " ") );};
$.parseParams = function(query) {
    var params = {}, e;
    while ( e = re.exec(query) ) {
        var k = decode( e[1] ), v = decode( e[2] );
        if (k.substring(k.length - 2) === '[]') {
            k = k.substring(0, k.length - 2);
            (params[k] || (params[k] = [])).push(v);
        }
        else params[k] = v;
    }
    return params;
};
})(jQuery);

fork at https://gist.github.com/956897

在https://gist.github.com/956897上叉

#15


-1  

You can use the function .serializeArray() (Link) of jQuery itself. This function returns an array of key-value pair. Result example:

您可以使用jQuery本身的函数. serializearray()(链接)。该函数返回键值对的数组。结果示例:

[
  { name: "id", value: "1" },
  { name: "version", value: "100" }
]

#1


56  

You should use jQuery BBQ's deparam function. It's well-tested and documented.

您应该使用jQuery BBQ的deparam函数。它是经过良好测试的和记录。

#2


28  

This is a slightly modified version of a function I wrote a while ago to do something similar.

这是一个稍微修改过的函数,我之前写过类似的东西。

var QueryStringToHash = function QueryStringToHash  (query) {
  var query_string = {};
  var vars = query.split("&");
  for (var i=0;i<vars.length;i++) {
    var pair = vars[i].split("=");
    pair[0] = decodeURIComponent(pair[0]);
    pair[1] = decodeURIComponent(pair[1]);
        // If first entry with this name
    if (typeof query_string[pair[0]] === "undefined") {
      query_string[pair[0]] = pair[1];
        // If second entry with this name
    } else if (typeof query_string[pair[0]] === "string") {
      var arr = [ query_string[pair[0]], pair[1] ];
      query_string[pair[0]] = arr;
        // If third or later entry with this name
    } else {
      query_string[pair[0]].push(pair[1]);
    }
  } 
  return query_string;
};

#3


16  

How about this short functional approach?

那么这个简短的函数方法呢?

function parseParams(str) {
    return str.split('&').reduce(function (params, param) {
        var paramSplit = param.split('=').map(function (value) {
            return decodeURIComponent(value.replace(/\+/g, ' '));
        });
        params[paramSplit[0]] = paramSplit[1];
        return params;
    }, {});
}

Example:

例子:

parseParams("this=is&just=an&example") // Object {this: "is", just: "an", example: undefined}

#4


13  

My answer:

我的回答:

function(query){
  var setValue = function(root, path, value){
    if(path.length > 1){
      var dir = path.shift();
      if( typeof root[dir] == 'undefined' ){
        root[dir] = path[0] == '' ? [] : {};
      }

      arguments.callee(root[dir], path, value);
    }else{
      if( root instanceof Array ){
        root.push(value);
      }else{
        root[path] = value;
      }
    }
  };
  var nvp = query.split('&');
  var data = {};
  for( var i = 0 ; i < nvp.length ; i++ ){
    var pair = nvp[i].split('=');
    var name = decodeURIComponent(pair[0]);
    var value = decodeURIComponent(pair[1]);

    var path = name.match(/(^[^\[]+)(\[.*\]$)?/);
    var first = path[1];
    if(path[2]){
      //case of 'array[level1]' || 'array[level1][level2]'
      path = path[2].match(/(?=\[(.*)\]$)/)[1].split('][')
    }else{
      //case of 'name'
      path = [];
    }
    path.unshift(first);

    setValue(data, path, value);
  }
  return data;
}

#5


9  

I am using David Dorward's answer, and realized that it doesn't behave like PHP or Ruby on Rails how they parse the params:

我正在使用David Dorward的回答,并意识到它不像PHP或Ruby on Rails那样,如何解析params:

1) a variable is only an array if it ends with [], such as ?choice[]=1&choice[]=12, not when it is ?a=1&a=2

1)一个变量仅是一个数组,如果它以[],比如?choice[]=1&choice[]=12,而不是当它是?a=1&a=2。

2) when mulitple params exist with the same name, the later ones replaces the earlier ones, as on PHP servers (Ruby on Rails keep the first one and ignore the later ones), such as ?a=1&b=2&a=3

当mulitple params以相同的名称存在时,后面的函数将替换前面的那些,如PHP服务器(Ruby on Rails保留第一个,忽略后面的),例如?a=1&b=2&a=3。

So modifying David's version, I have:

所以修改大卫的版本,我有:

function QueryStringToHash(query) {

  if (query == '') return null;

  var hash = {};

  var vars = query.split("&");

  for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split("=");
    var k = decodeURIComponent(pair[0]);
    var v = decodeURIComponent(pair[1]);

    // If it is the first entry with this name
    if (typeof hash[k] === "undefined") {

      if (k.substr(k.length-2) != '[]')  // not end with []. cannot use negative index as IE doesn't understand it
        hash[k] = v;
      else
        hash[k.substr(0, k.length-2)] = [v];

    // If subsequent entry with this name and not array
    } else if (typeof hash[k] === "string") {
      hash[k] = v;  // replace it

    // If subsequent entry with this name and is array
    } else {
      hash[k.substr(0, k.length-2)].push(v);
    }
  } 
  return hash;
};

which is tested fairly thoroughly.

这是相当彻底的测试。

#6


6  

Here's how you could create a new jQuery function:

下面是如何创建一个新的jQuery函数:

jQuery.unparam = function (value) {
    var
    // Object that holds names => values.
    params = {},
    // Get query string pieces (separated by &)
    pieces = value.split('&'),
    // Temporary variables used in loop.
    pair, i, l;

    // Loop through query string pieces and assign params.
    for (i = 0, l = pieces.length; i < l; i++) {
        pair = pieces[i].split('=', 2);
        // Repeated parameters with the same name are overwritten. Parameters
        // with no value get set to boolean true.
        params[decodeURIComponent(pair[0])] = (pair.length == 2 ?
            decodeURIComponent(pair[1].replace(/\+/g, ' ')) : true);
    }

    return params;
};

#7


6  

Thanks to him http://james.padolsey.com/javascript/parsing-urls-with-the-dom/

由于他http://james.padolsey.com/javascript/parsing-urls-with-the-dom/

Pretty easy :D

很简单:D

function params_unserialize(p){
var ret = {},
    seg = p.replace(/^\?/,'').split('&'),
    len = seg.length, i = 0, s;
for (;i<len;i++) {
    if (!seg[i]) { continue; }
    s = seg[i].split('=');
    ret[s[0]] = s[1];
}
return ret;}

#8


6  

I know this is an old thread, but maybe there is still some relevance in it?

我知道这是一个古老的线索,但也许它仍然有关联?

Inspired by Jacky Li's good solution I tried a slight variation of my own with the objective to also be able to take care of arbitrary combinations of arrays and objects as input. I looked at how PHP would have done it and tried to get something "similar" going. Here is my code:

在Jacky Li的良好解决方案的启发下,我尝试了自己的一个微小的变化,目标也可以处理任意组合的数组和对象作为输入。我查看了PHP是如何做到的,并试图得到类似的结果。这是我的代码:

function getargs(str){
   var ret={};
   function build(urlnam,urlval,obj){ // extend the return object ...
    var i,k,o=obj, x, rx=/\[([^\]]*)\]/g, idx=[urlnam.replace(rx,'')];
    while (x=rx.exec(urlnam)) idx.push(x[1]); 
    while(true){
     k=idx.shift();
     if(k.trim()=='') {// key is empty: autoincremented index
       if (o.constructor.name=='Array') k=o.length; // for Array
       else if (o===obj ) {k=null}  // for first level property name
       else {k=-1;                                  // for Object
         for(i in o) if (+i>k) k=+i;
         k++;
       }
     }
     if(idx.length) { 
       // set up an array if the next key (idx[0]) appears to be
       // numeric or empty, otherwise set up an object:
       if (o[k]==null || typeof o[k]!='object') o[k]=isNaN(idx[0])?{}:[]; 
       o=o[k]; // move on to the next level
     }
     else { // OK, time to store the urlval in its chosen place ...
       // console.log('key',k,'val',urlval);                 
       o[k]=urlval===""?null:urlval; break; // ... and leave the while loop.
     } 
    }
    return obj;
   }
   // ncnvt: is a flag that governs the conversion of
   // numeric strings into numbers
   var ncnvt=true,i,k,p,v,argarr=[],
       ar=(str||window.location.search.substring(1)).split("&"),
       l=ar.length;
   for (i=0;i<l;i++) {if (ar[i]==="") continue;
     p=ar[i].split("=");k=decodeURIComponent(p[0]);
     v=p[1];v=(v!=null)?decodeURIComponent(v.replace(/\+/g,'%20')):'';
     if (ncnvt && v.trim()>"" && !isNaN(v)) v-=0;
     argarr.push([k,v]);  // array: key-value-pairs of all arguments
   }
   for (i=0,l=argarr.length;i<l;i++) build(argarr[i][0],argarr[i][1],ret);
   return ret;
}

If the function is called without the str-argument it will assume window.location.search.slice(1) as input.

如果函数在没有字符串参数的情况下被调用,它将假设window.location.search.slice(1)作为输入。

Some examples:

一些例子:

['a=1&a=2',                               // 1
 'x[y][0][z][]=1',                        // 2
 'hello=[%22world%22]&world=hello',       // 3
 'a=1&a=2&&b&c=3&d=&=e&',                 // 4
 'fld[2][]=2&fld[][]=3&fld[3][]=4&fld[]=bb&fld[]=cc',  // 5
 $.param({a:[[1,2],[3,4],{aa:'one',bb:'two'},[5,6]]}), // 6
 'a[]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13',// 7
 'a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13'// 8
].map(function(v){return JSON.stringify(getargs(v));}).join('\n')

results in

结果

{"a":2}                                    // 1
{"x":{"y":[{"z":[1]}]}}                    // 2
{"hello":"[\"world\"]","world":"hello"}    // 3
{"a":2,"b":null,"c":3,"d":null,"null":"e"} // 4 = { a: 2, b: null, c: 3, d: null, null: "e" }
{"fld":[null,null,[2],[3,4],"bb","cc"]}    // 5 
{"a":[[1,2],[3,4],{"aa":"one","bb":"two"},[5,6]]}  // 6
{"a":["hi",2,null,[7,99],13]}              // 7
{"a":{"0":2,"3":[7,99],"4":13,"x":"hi"}}   // 8

Whereas Jacky Li's solution would produce the outer container for a as a plain object

而Jacky Li的解决方案则是将a作为一个普通对象生成外部容器。

{a:{"0":["1","2"],"1":["3","4"],"2":["5","6"]}} // 6: JackyLi's output

getargs() looks at the first given index for any level to determine whether this level will be an object (non-numeric index) or an array (numeric or empty), thus resulting in the output as shown in the listing bove (no. 6).

getargs()查看任何级别的第一个给定索引,以确定该级别是否为对象(非数字索引)或数组(数字或空),从而导致输出如清单bove所示(不)。6)。

If the current object is an array then nulls get inserted wherever necessary to represent empty positions. Arrays are always consecutively numbered and 0-based).

如果当前对象是一个数组,则在必要时插入null,以表示空位置。数组总是连续编号和基于0的。

Note, that in the example no. 8 the "autoincrement" for empty indices still works, even though we are dealing with an object now and not an array.

注意,在例子中没有。空索引的“自动增量”仍然有效,尽管我们现在处理的是对象而不是数组。

As far as I have tested it, my getargs() behaves pretty much identically to Chriss Roger's great jQuery $.deparam() plugin mentioned in the accepted answer. The main difference is that getargs runs without jQuery and that it does autoincrement in objects while $.deparam() will not do that:

在我测试过的情况下,我的getargs()行为几乎完全相同于Chriss Roger的jQuery $.deparam()插件。主要的区别是getargs没有jQuery,它在对象中自动递增,而$.deparam()不会这样做:

JSON.stringify($.deparam('a[x]=hi&a[]=2&a[3][]=7&a[3][]=99&a[]=13').a);

results in

结果

{"3":["7","99"],"x":"hi","undefined":"13"}

In $.deparam() the index [] is interpreted as an undefined instead of an autoincremented numerical index.

在$.deparam()中,索引[]被解释为一个未定义的,而不是一个自动递增的数值索引。

#9


3  

Here's my JavaScript implementation which I use in a server-side JScript ASP Classic page (demo):

下面是我在服务器端JScript ASP经典页面(demo)中使用的JavaScript实现:

// Transforms a query string in the form x[y][0][z][]=1 into {x:{y:[{z:[1]}]}}
function parseJQueryParams(p) {
    var params = {};
    var pairs = p.split('&');
    for (var i=0; i<pairs.length; i++) {
        var pair = pairs[i].split('=');
        var indices = [];
        var name = decodeURIComponent(pair[0]),
            value = decodeURIComponent(pair[1]);

        var name = name.replace(/\[([^\]]*)\]/g, 
            function(k, idx) { indices.push(idx); return ""; });

        indices.unshift(name);
        var o = params;

        for (var j=0; j<indices.length-1; j++) {
            var idx = indices[j];
            var nextIdx = indices[j+1];
            if (!o[idx]) {
                if ((nextIdx == "") || (/^[0-9]+$/.test(nextIdx)))
                    o[idx] = [];
                else
                    o[idx] = {};
            }
            o = o[idx];
        }

        idx = indices[indices.length-1];
        if (idx == "") {
            o.push(value);
        }
        else {
            o[idx] = value;
        }
    }
    return params;
}

#10


0  

This is my version in Coffeescript. Also works for url like http://localhost:4567/index.html?hello=[%22world%22]&world=hello#/home

这是我在Coffeescript的版本。也适用于url,例如http://localhost:4567/index.html?hello=[%22 %22]&world=hello#/home。

getQueryString: (url)->
    return null if typeof url isnt 'string' or url.indexOf("http") is -1

    split = url.split "?"

    return null if split.length < 2 
    path = split[1]

    hash_pos = path.indexOf "#"
    path = path[0...hash_pos] if hash_pos isnt -1

    data = path.split "&"
    ret = {}
    for d in data
      [name, val] = d.split "=" 
      name = decodeURIComponent name
      val = decodeURIComponent val
      try 
        ret[name] = JSON.parse val
      catch error
        ret[name] = val
    return ret

#11


0  

I came up with this solution, which behaves like the .Net function HttpUtility.ParseQueryString.

我提出了这个解决方案,它的行为像。net函数HttpUtility.ParseQueryString。

In the result, the query string parameters are store in properties as lists of values, so that qsObj["param"] will be the same as calling GetValues("param") in .Net.

在结果中,查询字符串参数作为值列表存储在属性中,因此qsObj[“param”]将与. net中调用GetValues(“param”)相同。

I hope you like it. JQuery not required.

我希望你喜欢。JQuery不是必需的。

var parseQueryString = function (querystring) {
    var qsObj = new Object();
    if (querystring) {
        var parts = querystring.replace(/\?/, "").split("&");
        var up = function (k, v) {
            var a = qsObj[k];
            if (typeof a == "undefined") {
                qsObj[k] = [v];
            }
            else if (a instanceof Array) {
                a.push(v);
            }
        };
        for (var i in parts) {
            var part = parts[i];
            var kv = part.split('=');
            if (kv.length == 1) {
                var v = decodeURIComponent(kv[0] || "");
                up(null, v);
            }
            else if (kv.length > 1) {
                var k = decodeURIComponent(kv[0] || "");
                var v = decodeURIComponent(kv[1] || "");
                up(k, v);
            }
        }
    }
    return qsObj;
};

Here is how to use it:

下面是如何使用它:

var qsObj = parseQueryString("a=1&a=2&&b&c=3&d=&=e&");

To preview the result in the console juste type in:

要在控制台中预览结果,请输入:

JSON.stringify(qsObj)

Output:

输出:

"{"a":["1","2"],"null":["","b",""],"c":["3"],"d":[""],"":["e"]}"

#12


0  

There's a beautiful one-liner over at CSS-Tricks (original source from Nicholas Ortenzio):

在css -把戏中有一个漂亮的俏皮话(来自尼古拉斯·奥登齐奥的原始资料):

function getQueryParameters(str) {
    return (str || document.location.search).replace(/(^\?)/,'').split("&").map(function(n){return n = n.split("="),this[n[0]] = n[1],this}.bind({}))[0];
}

The really clever part is how it uses the anonymous function's this object, adding a key/value pair for each of the queries in the string. That said, there's some room for improvement. I've modified it a bit below, with the following changes:

真正聪明的部分是它如何使用匿名函数的这个对象,在字符串中为每个查询添加一个键/值对。这就是说,还有一些改进的空间。我已经修改了下面的内容,下面的修改如下:

  1. Added handling of empty strings and non-string input.

    添加处理空字符串和非字符串输入。

  2. Handled URI-encoded strings (%40->@, etc).

    处理uri编码的字符串(%40->@,等等)。

  3. Removed the default use of document.location.search when the input was empty.

    删除document.location的默认使用。在输入为空时进行搜索。

  4. Changed the name, made it more readable, added comments.

    更改了名称,使其更具可读性,添加了注释。

function deparam(str) {
    // Uses an empty 'this' to build up the results internally
    function splitQuery(query) {
        query = query.split('=').map(decodeURIComponent);
        this[query[0]] = query[1];
        return this;
    }

    // Catch bad input
    if (!str || !(typeof str === 'string' || str instanceof String))
        return {};

    // Split the string, run splitQuery on each piece, and return 'this'
    var queries = str.replace(/(^\?)/,'').split('&');
    return queries.map(splitQuery.bind({}))[0];
}

#13


0  

Here's a simple & compact one if you only want to quickly get the parameters from a GET request:

如果您只想快速获得get请求中的参数,这里有一个简单紧凑的示例:

function httpGet() {
    var a={},b,i,q=location.search.replace(/^\?/,"").split(/\&/);
    for(i in q) if(q[i]) {b=q[i].split("=");if(b[0]) a[b[0]]=
    decodeURIComponent(b[1]).replace(/\+/g," ");} return a;
}

It converts

它转换

something?aa=1&bb=2&cc=3

into an object like

成一个对象

{aa:1,bb:2,cc:3}

#14


-1  

answers could use a bit of jQuery elegance:

答案可以用一点jQuery的优雅:

(function($) {
var re = /([^&=]+)=?([^&]*)/g;
var decodeRE = /\+/g; // Regex for replacing addition symbol with a space
var decode = function (str) {return decodeURIComponent( str.replace(decodeRE, " ") );};
$.parseParams = function(query) {
    var params = {}, e;
    while ( e = re.exec(query) ) {
        var k = decode( e[1] ), v = decode( e[2] );
        if (k.substring(k.length - 2) === '[]') {
            k = k.substring(0, k.length - 2);
            (params[k] || (params[k] = [])).push(v);
        }
        else params[k] = v;
    }
    return params;
};
})(jQuery);

fork at https://gist.github.com/956897

在https://gist.github.com/956897上叉

#15


-1  

You can use the function .serializeArray() (Link) of jQuery itself. This function returns an array of key-value pair. Result example:

您可以使用jQuery本身的函数. serializearray()(链接)。该函数返回键值对的数组。结果示例:

[
  { name: "id", value: "1" },
  { name: "version", value: "100" }
]