ฟังก์ชันผกผัน $ .param () ใน JavaScript / jQuery


122

รับแบบฟอร์มต่อไปนี้:

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

ฉันสามารถใช้$.param( .. )โครงสร้างเพื่อจัดลำดับแบบฟอร์ม:

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

=> foo=bar&hello=hello+world

ฉันจะถอนการติดตั้งสตริงด้านบนด้วย JavaScript และรับแฮชกลับได้อย่างไร

ตัวอย่างเช่น,

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

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

อ้างอิง: jQuery.param( obj ).


2
เฮ้ฉันแค่เพิ่มความคิดเห็นนี้เพื่อให้คุณสามารถเห็นการอัปเดตที่ฉันทำกับโค้ดในกรณีที่คุณกำลังใช้งานอยู่ ... ฉันตั้งใจเขียนมันขึ้นมาเพื่อแทนที่ความคิดเห็นแรก+เท่านั้น ตอนนี้มันแทนที่พวกเขาทั้งหมด!
Blixt

มีปลั๊กอินที่เรียกว่าQueryString. ฉันสร้างขึ้นมา แต่ไม่ยอมรับพารามิเตอร์มันอ่านจาก window.location.search เท่านั้น ฉันจำคนอื่นที่ยอมรับพารามิเตอร์ ...
BrunoLM

1
refactored jquery BBQ deparam () วิธีการเป็นโมดูล NPM โดยไม่ต้องพึ่งพาnpmjs.com/package/deparam
alexey2baranov

alexey2baranov วิธีการ refactoring deparam () โดยไม่มี NPM เป็นการพึ่งพา? :)
Andrew

คำตอบ:


62

คุณควรใช้ฟังก์ชันdeparamของjQuery BBQ ผ่านการทดสอบและบันทึกไว้เป็นอย่างดี


ปลั๊กอินที่ดี! ขอบคุณสำหรับการแบ่งปัน.
Jonathan

29
หากคุณไม่ต้องการรับปลั๊กอินบาร์บีคิวทั้งหมดฟังก์ชัน deparam ถูกแยกออกมาเป็นปลั๊กอินแบบสแตนด์อโลนที่นี่: github.com/chrissrogers/jquery-deparam
Felipe Castro

2
น่าเสียดายที่หน้า github ไม่เห็นการอัปเดตใด ๆ ในช่วงหลายปีที่ผ่านมาและเมื่อฉันลองแล้วดูเหมือนว่าจะไม่เข้ากันกับ jQuery ล่าสุด ... ดูเหมือนว่าฉันต้องการอะไร
pilavdzice

31

นี่เป็นฟังก์ชันเวอร์ชันแก้ไขเล็กน้อยที่ฉันเขียนเมื่อสักครู่ที่ผ่านมาเพื่อทำสิ่งที่คล้ายคลึง

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;
};

1
สิ่งที่ฉันคิดกับคำตอบที่ยอมรับ "สิ่งนี้ใช้ไม่ได้กับอาร์เรย์" โซลูชันของคุณใช้งานได้ดี
Robert Koritnik

20

วิธีการทำงานสั้น ๆ นี้เป็นอย่างไร?

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;
    }, {});
}

ตัวอย่าง:

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

1
นี่ควรเป็นคำตอบที่ได้รับการยอมรับไม่มีการพึ่งพาภายนอก
Michael Robinson

โซลูชันที่เรียบง่ายเชื่อถือได้และมีประสิทธิภาพ กราบครับท่าน
fmquaglia

5
สำหรับสิ่งที่ทำมันเป็นทางออกที่ดีอย่างแน่นอน แต่จะไม่ดูแลอาร์เรย์หรือวัตถุที่ส่งผ่าน url ที่field[][]=a&field[0][]=b&field[0][]=cได้รับการดำเนินการตามที่มันควรจะเป็นObject { field[][]: "a", field[0][]: "c" } resultobject.field[0] = Array [ "a", "b", "c" ]นี่คือลักษณะการทำงานตามที่คาดไว้จาก PHP โซลูชันของ @ JackyLi ดูแลเรื่องนั้น
cars10m

16

คำตอบของฉัน:

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;
}

ใช่ ใช่ ใช่ นี่คือสิ่งที่แน่นอนที่ฉันต้องการในการแยกวิเคราะห์พารามิเตอร์ที่ JQuery ส่งมาในการโทร $ .ajax สิ่งนี้ส่งคืนแฮชที่ซ้อนกันอย่างถูกต้อง ขอบคุณมาก Jacky Li!
Pascal Lindelauf

ทางออกที่ดีที่สุด - มันค่อนข้างดี! แต่เมื่อฉันใช้JSON.stringify(geturlargs('fld[2][]=2&fld[][]=3&fld[3][]=4&fld[]=bb&fld[]=cc').fld)ฉันได้รับ{"2":["2"],"3":["4"],"":"cc"}และไม่ใช่[null,null,[2],[3,4],"bb","cc"]สิ่งที่ฉันหวังไว้ (นี่คือสิ่งที่ PHP จะให้ฉัน)
cars10m

1
นี่คือคำตอบที่ถูกต้องและโปรดเพิกเฉยต่อคำตอบอื่น ๆ ทั้งหมดมันทำงานไม่ถูกต้อง
Andrew

1
คำตอบนี้เป็นคำตอบเดียวที่กล่าวถึงกรณีการใช้งานของฉันโดยเฉพาะ (ที่ฉันส่งผ่านวัตถุที่มีคีย์ / ค่าซ้อนกันไปยัง $ .param ของ jQuery ซึ่งจะช่วยให้ค่าเหล่านั้นเพียงพอเมื่อเรียกค้น)
delinear

9

ฉันใช้คำตอบของ David Dorward และตระหนักว่ามันไม่ได้ทำงานเหมือน PHP หรือ Ruby on Rails วิธีที่พวกเขาแยกวิเคราะห์พารามิเตอร์:

1) ตัวแปรเป็นเพียงอาร์เรย์ถ้ามันลงท้ายด้วย[]เช่น?choice[]=1&choice[]=12ไม่ใช่เมื่อมันเป็น?a=1&a=2

2) เมื่อมีพารามิเตอร์หลายตัวที่มีชื่อเดียวกันตัวต่อมาจะแทนที่พารามิเตอร์ก่อนหน้าเช่นเดียวกับบนเซิร์ฟเวอร์ PHP (Ruby on Rails จะเก็บอันแรกและเพิกเฉยต่อพารามิเตอร์ในภายหลัง) เช่น ?a=1&b=2&a=3

ดังนั้นการปรับเปลี่ยนเวอร์ชันของ David ฉันมี:

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;
};

ซึ่งผ่านการทดสอบอย่างละเอียดพอสมควร


ข้อมูลจำเพาะของ uri คือ a = 1 & a = 2 ควรเป็นอาร์เรย์ Ruby on Rails และ PHP ไม่เป็นไปตามข้อกำหนดจริง
adiktofsugar

บรรทัดที่คุณต่อท้ายอาร์เรย์ควรเป็นhash[k.substr(0, k.length-2)] = [v];และhash[k.substr(0, k.length-2)].push(v);
Baptiste Pernet

คงจะดีไม่น้อยหากสิ่งนี้สามารถใช้ได้จนถึงเวลา npm
Erik van Velzen

7

ฉันรู้ว่านี่เป็นกระทู้เก่า แต่อาจมีความเกี่ยวข้องอยู่บ้าง?

แรงบันดาลใจจากวิธีแก้ปัญหาที่ดีของ 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;
}

หากฟังก์ชันถูกเรียกโดยไม่มี - strอาร์กิวเมนต์จะถือว่า window.location.search.slice(1)เป็นอินพุต

ตัวอย่างบางส่วน:

['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')

ผลลัพธ์ใน

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

ในขณะที่วิธีการแก้ปัญหาของ Jacky Li จะผลิตภาชนะชั้นนอกสำหรับaเป็นวัตถุธรรมดา

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

getargs() ดูดัชนีที่กำหนดแรกสำหรับระดับใด ๆ เพื่อพิจารณาว่าระดับนี้จะเป็นวัตถุ (ดัชนีที่ไม่ใช่ตัวเลข) หรืออาร์เรย์ (ตัวเลขหรือว่างเปล่า) จึงทำให้ได้ผลลัพธ์ตามที่แสดงในรายการด้านบน (หมายเลข 6)

หากออบเจ็กต์ปัจจุบันเป็นอาร์เรย์จะnullมีการแทรกเมื่อจำเป็นเพื่อแสดงตำแหน่งว่าง อาร์เรย์จะมีหมายเลขตามลำดับและอิง 0 เสมอ)

โปรดทราบว่าในตัวอย่างไม่มี 8 "การสร้างอัตโนมัติ" สำหรับดัชนีว่างยังคงใช้งานได้แม้ว่าตอนนี้เรากำลังจัดการกับออบเจ็กต์ไม่ใช่อาร์เรย์ก็ตาม

เท่าที่ฉันได้ทดสอบแล้วgetargs()พฤติกรรมของฉันค่อนข้างเหมือนกับ$.deparam() ปลั๊กอิน jQuery ที่ยอดเยี่ยมของ Chriss Roger ที่กล่าวถึงในคำตอบที่ยอมรับ ความแตกต่างที่สำคัญคือgetargsทำงานโดยไม่มี jQuery และมันจะสร้างอัตโนมัติในวัตถุในขณะที่$.deparam()จะไม่ทำเช่นนั้น:

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

ผลลัพธ์ใน

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

ใน$.deparam()ดัชนี[]จะถูกตีความว่าเป็นundefinedแทนที่จะเป็นดัชนีตัวเลขที่เพิ่มอัตโนมัติ


ขอบคุณสำหรับฟังก์ชั่นที่ยอดเยี่ยมนี้ อย่างไรก็ตามฉันสังเกตเห็นว่าถ้าคุณใช้ number เป็นคีย์ในอาร์เรย์เช่น '? a [5] [] = x' คีย์จะถูกใช้เป็นตัวเลขเมื่อสร้างอ็อบเจกต์ดังนั้นจึงสร้างองค์ประกอบว่าง 5 รายการในกรณีของฉัน ควรถือว่าคีย์ตัวเลขเป็นสตริงจึงสร้างออบเจ็กต์ที่มี "5" (พร้อมเครื่องหมายคำพูด) เป็นคีย์และ x เป็นค่า ฉันสามารถบังคับให้ url เป็น '? a ["5"] [] = x' แต่มันน่าเกลียด ...
Andrew

@ แอนดรูว์: นี่เป็นการตัดสินใจออกแบบโดยเจตนาในส่วนของฉัน: เท่าที่ฉันจำได้โซลูชันของแจ็คจะทำงานในแบบที่คุณคาดหวังมากขึ้น ฉันแนะนำบรรทัดo[k]=isNaN(idx[0])?{}:[];ด้วยความตั้งใจในการสร้างอาร์เรย์เมื่อใดก็ตามที่ฉันพบดัชนีตัวเลขเป็นดัชนีแรกที่กำหนดให้กับวัตถุใหม่ มิฉะนั้นฉันจะสร้างวัตถุทั่วไป ขึ้นอยู่กับคุณที่จะแก้ไขส่วนนั้นของโค้ดให้เหมาะกับความต้องการของคุณมากขึ้น I. จ. บางอย่างเช่นo[k]={}ควรทำเคล็ดลับ
cars10m

ขอบคุณ ป.ล. คุณควรลบ console.log กลางฟังก์ชันของคุณอย่างแน่นอน;)
Andrew

@ แอนดรูว์: ขอบคุณเพียงแสดงความคิดเห็นออกมา ต้องมองข้ามมันไปเมื่อฉันโพสต์รหัส
cars10m

6

นี่คือวิธีที่คุณสามารถสร้างฟังก์ชัน 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;
};

4
ฉันไม่ชอบฟังก์ชั่นนี้ เหตุใดพารามิเตอร์ที่ไม่มีค่าจึงควรได้ค่าเป็น 'จริง' ทำไมไม่ว่าง ฉันคิดว่าการตัดสินใจออกแบบนี้อาจนำไปสู่ข้อบกพร่องที่ลึกซึ้งมาก นอกจากนี้ทำไมไม่จัดการสถานการณ์ที่พารามิเตอร์สามารถมีได้หลายค่าแทนที่จะเลือกค่า 'สุดท้าย' โซลูชันที่โพสต์โดย David นั้นดีกว่ามาก
SolutionYogi

4
มันเป็นtrueหนึ่งเพื่อให้สามารถตรวจสอบif (params.redirect)หรือคล้ายกัน ถ้าคุณต้องการที่แตกต่างกันระหว่างtrueและค่าอื่น ๆ if (params.redirect === true)ที่คุณจะใช้ nullค่าจะไม่ช่วยในทางใด ๆ ที่ฉันสามารถคิด เหตุผลที่ฉันไม่ทำเหมือนเดวิดเพราะฉันให้ความสำคัญกับความยืดหยุ่นมากกว่า ด้วยวิธีการของเขาฉันต้องตรวจสอบว่าค่าเป็นสตริงหรืออาร์เรย์เพื่อใช้ค่าของมัน ในความคิดของฉันมันควรเป็นสตริงเสมอ ( trueค่าจะแปลงเป็น'true'สิ่งที่ฉันคิดว่าดี) หรือเป็นอาร์เรย์เสมอ ฉันเลือกสตริง
Blixt

โดยบัญชีนั้นหากเป็นพารามิเตอร์ลบมันจะถูกตั้งค่าเป็นจริงและฉันจะทำสิ่งที่เป็นอันตราย อย่างที่คุณเห็นการสร้างตัวอย่างเป็นเรื่องง่าย 'null' ระบุไว้อย่างชัดเจนว่าไม่มีค่าใด ๆ อยู่และการตัดสินใจจะถูกปล่อยให้ผู้เรียกใช้ว่าเขาต้องการตีความอย่างไร เกี่ยวกับค่าหลายค่าดูทางนี้ เมื่อกินหมดคุณจะต้องแน่ใจว่าผู้โทรคนใดคนหนึ่งจะใช้เวลาแก้ไขจุดบกพร่องว่าทำไมเขาถึงได้รับเพียงค่าเดียวหรือในภายหลังและแก้ไขโค้ด เมื่อส่งคืนอาร์เรย์ล่วงหน้าผู้โทรจะรู้วิธีจัดการทันที การทิ้งข้อมูลไม่ใช่เรื่องดี IMHO
SolutionYogi

2
หาก URL เป็นเช่น/abc?deleteนั้นฉันคาดว่าจะมีรายการสำหรับdelete. ฉันไม่เห็นว่ามันแตกต่างกันอย่างไร? ฉันไม่เห็นด้วยซ้ำว่าคุณจะชอบรหัสอื่นได้อย่างไรเพราะเหตุนี้รหัสนั้นจะตั้งค่าเป็นสตริง'undefined'ซึ่งไม่ดีกว่า และสำหรับค่าหลายค่ามันเป็นกรณีของความเรียบง่ายกับความยืดหยุ่น ฉันไม่ค่อยเห็นการใช้ค่าหลายค่าในสตริงการสืบค้น แต่ถ้าคุณต้องการให้ส่งคืนอาร์เรย์ที่มีค่า 1+ เสมอ อย่าผสมประเภทผลตอบแทน จากนั้นคุณจะต้องใช้เวลาในการดีบักเพราะโดยปกติแล้วสตริงอาจเป็นอาร์เรย์ได้
Blixt

ขอบคุณ ฉันไม่คิดว่าจะมีกระสุนเงิน ฉันเอาโค้ดของคุณไปแก้ไขเล็กน้อยลบค่าบูลีนเพิ่มการแยกวิเคราะห์อาร์เรย์พารามิเตอร์ ? foo [] = 1 & foo [] = 2 => foo: [ "1", "2"]
seb

6

ขอบคุณเขาhttp://james.padolsey.com/javascript/parsing-urls-with-the-dom/

ค่อนข้างง่าย: 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;}

2
วิธีนี้ใช้ไม่ได้กับกล่องเลือกที่มีหลายตัวเลือกเพราะจะเลือกไว้ล่าสุดเท่านั้น
Fernando Fabreti

ขออภัยฉันไม่เห็นประเด็นที่คุณอ้างถึงในความคิดเห็น ฟังก์ชันที่อ้างถึงในที่นี้คือการยกเลิกการกำหนดค่า / แยกวิเคราะห์ URI ด้วยพารามิเตอร์เหมือน?something=1&param2=value2ในอาร์เรย์ คุณหมายถึงอะไรกับ "do not work with select box with multiple options"?
brutuscat

4

นี่คือการใช้งาน JavaScript ของฉันซึ่งฉันใช้ในหน้าJScript ASP Classicฝั่งเซิร์ฟเวอร์( สาธิต ):

// 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;
}

จนถึงตอนนี้สิ่งที่ดีที่สุดที่ฉันพบสำหรับอาร์เรย์ที่ซ้อนกัน
ymakux

3

ใช้สิ่งนี้:

// convert query string to json object
var queryString = "cat=3&sort=1&page=1";

queryString
    .split("&")
    .forEach((item) => {
        const prop = item.split("=");
        filter[prop[0]] = prop[1];
    });

console.log(queryString);

1

HttpUtility.ParseQueryStringฉันมากับการแก้ปัญหานี้ซึ่งพฤติกรรมเช่นฟังก์ชั่นสุทธิ

ในผลลัพธ์พารามิเตอร์สตริงคิวรีจะถูกเก็บไว้ในคุณสมบัติเป็นรายการของค่าดังนั้นqsObj["param"]จะเหมือนกับการเรียกGetValues("param")ใน. Net

ฉันหวังว่าคุณจะชอบมัน. ไม่จำเป็นต้องใช้ 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;
};

นี่คือวิธีการใช้งาน:

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

หากต้องการดูผลลัพธ์ในคอนโซลให้พิมพ์:

JSON.stringify(qsObj)

เอาท์พุท:

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

1

มีหนึ่งซับที่สวยงามที่CSS-Tricks (ต้นฉบับจากNicholas Ortenzio ):

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];
}

ส่วนที่ฉลาดจริงๆคือการใช้thisอ็อบเจ็กต์ของฟังก์ชันที่ไม่ระบุตัวตนโดยเพิ่มคู่คีย์ / ค่าสำหรับแต่ละคิวรีในสตริง ที่กล่าวว่ามีช่องว่างสำหรับการปรับปรุง ฉันได้แก้ไขเล็กน้อยด้านล่างโดยมีการเปลี่ยนแปลงดังต่อไปนี้:

  1. เพิ่มการจัดการสตริงว่างและอินพุตที่ไม่ใช่สตริง

  2. จัดการสตริงที่เข้ารหัส URI ( %40-> @ฯลฯ )

  3. ลบการใช้งานเริ่มต้นdocument.location.searchเมื่ออินพุตว่างเปล่า

  4. เปลี่ยนชื่อทำให้อ่านง่ายขึ้นเพิ่มความคิดเห็น

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];
}

1

นี่เป็นคำถามเก่าจริงๆ แต่เมื่อฉันไปมาคนอื่นอาจมาที่โพสต์นี้และฉันต้องการรีเฟรชธีมนี้เล็กน้อย วันนี้ไม่จำเป็นต้องสร้างโซลูชันที่กำหนดเอง - มีอินเทอร์เฟซURLSearchParams

var paramsString = "q=URLUtils.searchParams&topic=api";
var searchParams = new URLSearchParams(paramsString);

//Iterate the search parameters.
for (let p of searchParams) {
  console.log(p);
}

ข้อ จำกัด เดียวที่ฉันรู้ - ฟีเจอร์นี้ไม่รองรับใน IE / Edge


น่าเสียดายที่ IE ไม่รองรับตามปกติในกรณีที่คุณต้องการรองรับเบราว์เซอร์นี้
Lauren

0

นี่คือเวอร์ชันของฉันใน Coffeescript ยังใช้ได้กับ url เช่น http://localhost:4567/index.html?hello=[%22world%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

0

นี่เป็นวิธีที่ง่ายและกะทัดรัดหากคุณต้องการรับพารามิเตอร์จากคำขอ 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;
}

มันแปลง

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

ลงในวัตถุเช่น

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

0

สร้างการแสดงอาร์เรย์หรืออ็อบเจ็กต์แบบอนุกรม (สามารถใช้เป็นสตริงเคียวรี URL สำหรับคำร้องขอ AJAX)

<button id='param'>GET</button> 
<div id="show"></div>
<script>
  $('#param').click(function () {
    var personObj = new Object();
    personObj.firstname = "vishal"
    personObj.lastname = "pambhar";
    document.getElementById('show').innerHTML=$.param(`personObj`));
  });
</script>
output:firstname=vishal&lastname=pambhar

1
รหัสที่ไม่มีคำอธิบายไม่ได้รับการต้อนรับ ช่วยอธิบายรหัสของคุณหน่อยได้ไหม
L. Guthardt

สร้างการแสดงอนุกรมของอาร์เรย์หรือวัตถุ (สามารถใช้เป็นสตริงการสืบค้น URL สำหรับคำขอ AJAX)
Vishal Patel

โปรดเพิ่มคำอธิบายโดยตรงในคำตอบของคุณโดยแก้ไข ไม่ได้อยู่ในความคิดเห็นแม้ว่า
L. Guthardt

-1

คำตอบสามารถใช้ความสง่างามของ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);

ส้อมที่https://gist.github.com/956897


-1

คุณสามารถใช้ฟังก์ชัน.serializeArray()( Link ) ของ jQuery เองได้ ฟังก์ชันนี้ส่งคืนอาร์เรย์ของคู่คีย์ - ค่า ตัวอย่างผลลัพธ์:

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

1
นี่ไม่ใช่สิ่งที่ถูกถาม เขาต้องการเปลี่ยนสตริงให้เป็นแฮช serializeArray ใช้รูปแบบและส่งคืนอาร์เรย์
Daniel Bang
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.