Làm cách nào để chuyển đổi các tham số URL thành đối tượng JavaScript?


223

Tôi có một chuỗi như thế này:

abc=foo&def=%5Basf%5D&xyz=5

Làm cách nào tôi có thể chuyển đổi nó thành một đối tượng JavaScript như thế này?

{
  abc: 'foo',
  def: '[asf]',
  xyz: 5
}


1
Đó không phải là: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/iến developer.mozilla.org/en-US/docs/Web/API/URL/ trộm (mặc dù chúng tôi sẽ phải chờ lâu hơn một chút cho tất cả các trình duyệt đã chọn cái này)
Arthur

Câu trả lời:


334

Biên tập

Chỉnh sửa này cải thiện và giải thích câu trả lời dựa trên các ý kiến.

var search = location.search.substring(1);
JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')

Thí dụ

Phân tích abc=foo&def=%5Basf%5D&xyz=5theo năm bước:

  • decodeURI: abc = foo & def = [asf] & xyz = 5
  • Báo giá thoát: tương tự, vì không có dấu ngoặc kép
  • Thay thế &: abc=foo","def=[asf]","xyz=5
  • Thay thế =: abc":"foo","def":"[asf]","xyz":"5
  • Suround với curlies và trích dẫn: {"abc":"foo","def":"[asf]","xyz":"5"}

JSON hợp pháp.

Một giải pháp cải tiến cho phép có nhiều ký tự hơn trong chuỗi tìm kiếm. Nó sử dụng chức năng phục hồi để giải mã URI:

var search = location.search.substring(1);
JSON.parse('{"' + search.replace(/&/g, '","').replace(/=/g,'":"') + '"}', function(key, value) { return key===""?value:decodeURIComponent(value) })

Thí dụ

search = "abc=foo&def=%5Basf%5D&xyz=5&foo=b%3Dar";

cho

Object {abc: "foo", def: "[asf]", xyz: "5", foo: "b=ar"}

Câu trả lời gốc

Một lớp lót:

JSON.parse('{"' + decodeURI("abc=foo&def=%5Basf%5D&xyz=5".replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}')

4
Để điều này hoạt động trong CoffeeScript, hãy thoát '=' trong regex. .replace (/ \ = / g, "\": \ "")
airlok

175
Đó không phải là một lớp lót ... đó là một trạm không gian.
Ziggy

5
tốt hơn nếu bạn sử dụngJSON.parse('{"' + decodeURI(location.search.substring(1).replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
Daniël Tulp

4
Điều này không thành công nếu bạn có một ký tự dấu bằng trong url cần phân tích cú pháp. EX: "cookie = dlksdlfj = sodkfjhsdlfj"
jholloman

3
Cũng không hoạt động khi bạn có một trong các tham số không có giá trị.
Sych

113

2020 ES6 / 7/8 và tiếp cận

Bắt đầu ES6 trở đi, Javascript cung cấp một số cấu trúc để tạo ra giải pháp hiệu quả cho vấn đề này.

Điều này bao gồm sử dụng URLSearchParamsiterators

let params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
params.get("abc"); // "foo"

Nếu trường hợp sử dụng của bạn yêu cầu bạn thực sự chuyển đổi nó thành đối tượng, bạn có thể thực hiện chức năng sau:

function paramsToObject(entries) {
  let result = {}
  for(let entry of entries) { // each 'entry' is a [key, value] tupple
    const [key, value] = entry;
    result[key] = value;
  }
  return result;
}

Demo cơ bản

const urlParams = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
const entries = urlParams.entries(); //returns an iterator of decoded [key,value] tuples
const params = paramsToObject(entries); //{abc:"foo",def:"[asf]",xyz:"5"}

Sử dụng Object.fromEntries và lây lan

Chúng ta có thể sử dụng Object.fromEntries (hiện đang ở giai đoạn 4), thay thế paramsToObjectbằng Object.fromEntries(entries).

Các cặp giá trị được lặp lại là các cặp tên-giá trị danh sách với khóa là tên và giá trị là giá trị.

URLParams, trả về một đối tượng có thể lặp lại , sử dụng toán tử trải rộng thay vì gọi .entriescũng sẽ mang lại các mục nhập theo thông số kỹ thuật của nó:

const urlParams = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
const params = Object.fromEntries(urlParams); // {abc: "foo", def: "[asf]", xyz: "5"}

Lưu ý: Tất cả các giá trị được tự động chuỗi theo thông số URLSearchParams

Nhiều khóa giống nhau

Như @siipe đã chỉ ra, các chuỗi chứa nhiều giá trị khóa giống nhau sẽ được ép buộc vào giá trị khả dụng cuối cùng: foo=first_value&foo=second_valuevề bản chất sẽ trở thành : {foo: "second_value"}.

Theo câu trả lời này: https://stackoverflow.com/a/1746566/1194694 không có thông số nào để quyết định làm gì với nó và mỗi khung có thể hành xử khác nhau.

Một trường hợp sử dụng phổ biến sẽ là nối hai giá trị giống nhau thành một mảng, biến đối tượng đầu ra thành:

{foo: ["first_value", "second_value"]}

Điều này có thể đạt được với mã sau đây:

const groupParamsByKey = (params) => [...params.entries()].reduce((acc, tuple) => {
 // getting the key and value from each tuple
 const [key, val] = tuple;
 if(acc.hasOwnProperty(key)) {
    // if the current key is already an array, we'll add the value to it
    if(Array.isArray(acc[key])) {
      acc[key] = [...acc[key], val]
    } else {
      // if it's not an array, but contains a value, we'll convert it into an array
      // and add the current value to it
      acc[key] = [acc[key], val];
    }
 } else {
  // plain assignment if no special case is present
  acc[key] = val;
 }

return acc;
}, {});

const params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5&def=dude');
const output = groupParamsByKey(params) // {abc: "foo", def: ["[asf]", "dude"], xyz: 5}

2
Tôi không đề xuất giải pháp này. URLSearchParams có thông số kỹ thuật phi logic ( developer.mozilla.org/en-US/docs/Web/API/
mẹo

1
Tôi xin lỗi nhưng logic không có gì để làm với nó. Người ta có thể lập luận rằng đó là một search stringtrình phân tích cú pháp - đó là những gì nó được thiết kế để làm, bất kể nó có liên quan đến một URL
silicakes

Object.fromEntrieskhông hoạt động cho các phím lặp đi lặp lại. Nếu chúng ta cố gắng làm một cái gì đó như ?foo=bar1&foo=bar2, chúng ta sẽ chỉ nhận được { foo: 'bar2' }. Ví dụ, đối tượng yêu cầu Node.js phân tích cú pháp dưới dạng{ foo: ['bar1', 'bar2'] }
Siipe

Bạn nói đúng, tuy nhiên điều này không có thông số kỹ thuật và nhiều ngôn ngữ có cách tiếp cận có ý kiến ​​về cách họ phân tích nó: stackoverflow.com/a/1746566/1194694
silicakes

Điều này có vẻ tốt với tôi, nhưng để có được các giá trị cho khóa lặp đi lặp lại, chúng ta có thể sử dụng điều này let temp={};Object.keys(params).map(key=>{temp[key]=urlParams.getAll(key)})
Tirumaleshwar Keregadde

45

ES6 một lớp lót. Sạch sẽ và đơn giản.

Object.fromEntries(new URLSearchParams(location.search));

Đối với trường hợp cụ thể của bạn, nó sẽ là:

console.log(
  Object.fromEntries(new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5'))
);


Điều này rơi vào con mồi của Gotchas. "http://place.com?foo=bar&hello=%40world&showThing"sản xuất{ hello: "@world", http://place.com?foo: "bar", showThing: "" }
Seph Reed

1
Bạn nên sử dụng nó với chuỗi truy vấn (từ location.search) như "foo = bar & hello =% 40world & showThing" chứ không phải toàn bộ url, như câu hỏi gợi ý.

1
Điều này có thể được sử dụng, nhưng thận trọng ?someValue=falsetrở thành{ someValue: "false" }
Simon

Nó không hoạt động cho các phím lặp đi lặp lại. Nếu chúng ta cố gắng làm một cái gì đó như ?foo=bar1&foo=bar2, chúng ta sẽ chỉ nhận được { foo: 'bar2' }. Đối tượng yêu cầu Node.js phân tích cú pháp dưới dạng{ foo: ['bar1', 'bar2'] }
Siipe

@SephReed, tôi tin rằng nhận xét của bạn được giải quyết với phiên bản cập nhật sử dụnglocation.search
KyleMit

27

Tách vào &để có được cặp tên / giá trị, sau đó tách từng cặp trên =. Đây là một ví dụ:

var str = "abc=foo&def=%5Basf%5D&xy%5Bz=5"
var obj = str.split("&").reduce(function(prev, curr, i, arr) {
    var p = curr.split("=");
    prev[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
    return prev;
}, {});

Một cách tiếp cận khác, sử dụng các biểu thức chính quy:

var obj = {}; 
str.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) {
    obj[decodeURIComponent(key)] = decodeURIComponent(value);
}); 

Điều này được điều chỉnh từ "Tìm kiếm và không thay thế" của John Resig .


tx! bạn cũng nên thêm decodeURIComponen (p [0]) ở bên trái :)
Alex

Ví dụ đầu tiên không hoạt động với chuỗi truy vấn trống.
Michał Perłakowski

18

Một giải pháp ngắn gọn:

location.search
  .slice(1)
  .split('&')
  .map(p => p.split('='))
  .reduce((obj, pair) => {
    const [key, value] = pair.map(decodeURIComponent);
    return ({ ...obj, [key]: value })
  }, {});

điều này không thành công với mảng tức là: x = 1 & x = 2
Sh eldeeb

16

Các giải pháp đề xuất tôi tìm thấy cho đến nay không bao gồm các kịch bản phức tạp hơn.

Tôi cần phải chuyển đổi một chuỗi truy vấn như

https://random.url.com?Target=Offer&Method=findAll&filters%5Bhas_goals_enabled%5D%5BTRUE%5D=1&filters%5Bstatus%5D=active&fields%5B%5D=id&fields%5B%5D=name&fields%5B%5D=default_goal_name

vào một đối tượng như:

{
    "Target": "Offer",
    "Method": "findAll",
    "fields": [
        "id",
        "name",
        "default_goal_name"
    ],
    "filters": {
        "has_goals_enabled": {
            "TRUE": "1"
        },
        "status": "active"
    }
}

HOẶC LÀ:

https://random.url.com?Target=Report&Method=getStats&fields%5B%5D=Offer.name&fields%5B%5D=Advertiser.company&fields%5B%5D=Stat.clicks&fields%5B%5D=Stat.conversions&fields%5B%5D=Stat.cpa&fields%5B%5D=Stat.payout&fields%5B%5D=Stat.date&fields%5B%5D=Stat.offer_id&fields%5B%5D=Affiliate.company&groups%5B%5D=Stat.offer_id&groups%5B%5D=Stat.date&filters%5BStat.affiliate_id%5D%5Bconditional%5D=EQUAL_TO&filters%5BStat.affiliate_id%5D%5Bvalues%5D=1831&limit=9999

VÀO:

{
    "Target": "Report",
    "Method": "getStats",
    "fields": [
        "Offer.name",
        "Advertiser.company",
        "Stat.clicks",
        "Stat.conversions",
        "Stat.cpa",
        "Stat.payout",
        "Stat.date",
        "Stat.offer_id",
        "Affiliate.company"
    ],
    "groups": [
        "Stat.offer_id",
        "Stat.date"
    ],
    "limit": "9999",
    "filters": {
        "Stat.affiliate_id": {
            "conditional": "EQUAL_TO",
            "values": "1831"
        }
    }
}

Tôi đã biên soạn và điều chỉnh nhiều giải pháp thành một giải pháp thực sự hiệu quả:

MÃ:

var getParamsAsObject = function (query) {

    query = query.substring(query.indexOf('?') + 1);

    var re = /([^&=]+)=?([^&]*)/g;
    var decodeRE = /\+/g;

    var decode = function (str) {
        return decodeURIComponent(str.replace(decodeRE, " "));
    };

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

    var assign = function (obj, keyPath, value) {
        var lastKeyIndex = keyPath.length - 1;
        for (var i = 0; i < lastKeyIndex; ++i) {
            var key = keyPath[i];
            if (!(key in obj))
                obj[key] = {}
            obj = obj[key];
        }
        obj[keyPath[lastKeyIndex]] = value;
    }

    for (var prop in params) {
        var structure = prop.split('[');
        if (structure.length > 1) {
            var levels = [];
            structure.forEach(function (item, i) {
                var key = item.replace(/[?[\]\\ ]/g, '');
                levels.push(key);
            });
            assign(params, levels, params[prop]);
            delete(params[prop]);
        }
    }
    return params;
};

Đây là câu trả lời tốt nhất, vì nó thực sự xử lý đúng các truy vấn phức tạp.
Georgy Ivanov

Tôi nghĩ rằng điều này chỉ làm phức tạp mọi thứ, tôi sẽ vượt qua obj=encodeURIComponent(JSON.stringify({what:{ever:','},i:['like']})).

15

Đây là phiên bản đơn giản, rõ ràng bạn sẽ muốn thêm một số kiểm tra lỗi:

var obj = {};
var pairs = queryString.split('&');
for(i in pairs){
    var split = pairs[i].split('=');
    obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}

1
Bạn không quên giải mã chuỗi để chuyển đổi% 5B và% 5D thành ký tự phải không?
jfriend00

@Alex - Bạn đã sử dụng mã cập nhật hoặc bản gốc? Bản gốc có một vấn đề và một lỗi đánh máy.
Justin Niessner

Nó không thể xử lý thông số chính xác khi giá trị của chúng chứa '='. Nó cắt các giá trị thành đầu tiên '='.
Greck

JSON.parse('{"' + decodeURIComponent(query.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'));làm việc cho tôi
Danil Gaponov

1
nó không hoạt động name[]=test1&name[]=test2và nó sẽ dẫn đếnname[]=test2
Rafee

10

Tôi đã tìm thấy $ .String.deparam là giải pháp được xây dựng hoàn chỉnh nhất (có thể thực hiện các đối tượng lồng nhau, v.v.). Kiểm tra các tài liệu .


chỉ cần chỉ ra nếu đầu vào của bạn luôn luôn là một chuỗi truy vấn được tuần tự hóa thì không cần phải lo lắng về việc lồng nhau và một giải pháp nhẹ hơn có lẽ tốt hơn
mattacular 27/12/11

Tất nhiên rồi ... nhưng nó đã được thực hiện và thử nghiệm rồi (ví dụ Justin quên giải mã URI trong câu trả lời ban đầu - đó là những vấn đề nhỏ có thể khiến mọi thứ phức tạp hơn nhiều so với ban đầu).
Daff

9

Cách tiếp cận một lớp lót 2019

Đối với trường hợp cụ thể của bạn:

Object.fromEntries(new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5'));

Đối với trường hợp chung hơn khi ai đó muốn phân tích các tham số truy vấn đến một đối tượng:

Object.fromEntries(new URLSearchParams(location.search));

Nếu bạn không thể sử dụng Object.fromEntries, điều này cũng sẽ hoạt động:

Array.from(new URLSearchParams(window.location.search)).reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});

Ngoài ra[...new URLSearchParams(window.location.search)].reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
dman

1
URLSearchParams có một số vấn đề mà điều này phá vỡ. "http://place.com?foo=bar&hello=%40world&showThingsản xuất { hello: "@world", http://place.com?foo: "bar", showThing: "" }. Hãy thử thêmstr.split("?").pop()
Seph Reed

7

Một giải pháp khác dựa trên tiêu chuẩn mới nhất của URLSearchParams ( https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams )

function getQueryParamsObject() {
  const searchParams = new URLSearchParams(location.search.slice(1));
  return searchParams
    ? _.fromPairs(Array.from(searchParams.entries()))
    : {};
}

Xin lưu ý rằng giải pháp này được sử dụng

Array.from ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from )

_.fromPairs ( https://lodash.com/docs#fromPairs ) của lodash vì mục đích đơn giản.

Thật dễ dàng để tạo ra một giải pháp tương thích hơn vì bạn có quyền truy cập vào trình tìm kiếm searchParams.entries () .


6

Tôi đã có cùng một vấn đề, đã thử các giải pháp ở đây, nhưng không có giải pháp nào thực sự hiệu quả, vì tôi có các mảng trong các tham số URL, như thế này:

?param[]=5&param[]=8&othr_param=abc&param[]=string

Vì vậy, tôi đã kết thúc việc viết hàm JS của riêng mình, điều này tạo ra một mảng nằm ngoài param trong URI:

/**
 * Creates an object from URL encoded data
 */
var createObjFromURI = function() {
    var uri = decodeURI(location.search.substr(1));
    var chunks = uri.split('&');
    var params = Object();

    for (var i=0; i < chunks.length ; i++) {
        var chunk = chunks[i].split('=');
        if(chunk[0].search("\\[\\]") !== -1) {
            if( typeof params[chunk[0]] === 'undefined' ) {
                params[chunk[0]] = [chunk[1]];

            } else {
                params[chunk[0]].push(chunk[1]);
            }


        } else {
            params[chunk[0]] = chunk[1];
        }
    }

    return params;
}

2
Điều này thực sự hữu ích và đã làm gần như chính xác những gì tôi muốn. Tuy nhiên, tôi không thích cách "[]" được giữ trong chiến thuật trong đối tượng nếu các tham số URL giống như: bacon [] = egg & bacon [] = toast. Vì vậy, tôi đã thêm vào một dòng sau if(chunk[0].search("\\[\\]") !== -1) {đóchunk[0]=chunk[0].replace(/\[\]$/,'');
rgbflawed

@rgbflawed bạn nên chỉnh sửa câu trả lời vì lợi ích của người đọc và mức độ dễ đọc trong tương lai
Webdess 22/2/19

Sử dụng constthay varvì bởi vì ai đó có thể làm createObjFromURI = 'some text'và sau đó họ sẽ làm rối mã. nếu bạn sử dụng constthì ai đó đang chạy createObjFromURI = 'some text'sẽ gây ra lỗi không thể gán giá trị cho biến không đổi.
Justin Liu

5

Sử dụng ES6, API URL và API URLSearchParams.

function objectifyQueryString(url) {
  let _url = new URL(url);
  let _params = new URLSearchParams(_url.search);
  let query = Array.from(_params.keys()).reduce((sum, value)=>{
    return Object.assign({[value]: _params.get(value)}, sum);
  }, {});
  return query;
}

5

ES6 một lớp lót (nếu chúng ta có thể gọi nó theo cách nhìn thấy đường dài)

[...new URLSearchParams(location.search).entries()].reduce((prev, [key,val]) => {prev[key] = val; return prev}, {})


2
Bạn cũng có thể phá hủy cấu trúc curcho một số rõ ràng thêm. .reduce((prev, [key, val]) => {prev[key] = val})
Allan Lei

tôi thích đề nghị của bạn Allan Lei. Tôi cập nhật câu trả lời của mình
fadomire

3

Khá dễ dàng khi sử dụng URLSearchParamsAPI Web JavaScript,

var paramsString = "q=forum&topic=api";

//returns an iterator object
var searchParams = new URLSearchParams(paramsString);

//Usage
for (let p of searchParams) {
  console.log(p);
}

//Get the query strings
console.log(searchParams.toString());

//You can also pass in objects

var paramsObject = {q:"forum",topic:"api"}

//returns an iterator object
var searchParams = new URLSearchParams(paramsObject);

//Usage
for (let p of searchParams) {
  console.log(p);
}

//Get the query strings
console.log(searchParams.toString());

Liên kết hữu ích

LƯU Ý : Không được hỗ trợ trong IE


3

Đối với Node JS, bạn có thể sử dụng API Node JS querystring:

const querystring = require('querystring');

querystring.parse('abc=foo&def=%5Basf%5D&xyz=5&foo=b%3Dar');
// returns the object

Tài liệu: https://nodejs.org/api/queryopes.html


2

Không có giải pháp bản địa mà tôi biết. Dojo có một phương thức unerialization tích hợp nếu bạn sử dụng khung đó một cách tình cờ.

Nếu không, bạn có thể tự thực hiện nó một cách đơn giản:

function unserialize(str) {
  str = decodeURIComponent(str);
  var chunks = str.split('&'),
      obj = {};
  for(var c=0; c < chunks.length; c++) {
    var split = chunks[c].split('=', 2);
    obj[split[0]] = split[1];
  }
  return obj;
}

chỉnh sửa: đã thêm decodeURIComponent ()


2

Có một thư viện gọn nhẹ có tên YouAreI.js đã được thử nghiệm và làm cho việc này thực sự dễ dàng.

YouAreI = require('YouAreI')
uri = new YouAreI('http://user:pass@www.example.com:3000/a/b/c?d=dad&e=1&f=12.3#fragment');

uri.query_get() => { d: 'dad', e: '1', f: '12.3' }

2

Một trong những cách đơn giản nhất để thực hiện việc này bằng giao diện URLSearchParam.

Dưới đây là đoạn mã làm việc:

let paramObj={},
    querystring=window.location.search,
    searchParams = new URLSearchParams(querystring);    

  //*** :loop to add key and values to the param object.
 searchParams.forEach(function(value, key) {
      paramObj[key] = value;
   });

1

Đây có vẻ là giải pháp tốt nhất vì nó cần xem xét nhiều tham số cùng tên.

    function paramsToJSON(str) {
        var pairs = str.split('&');
        var result = {};
        pairs.forEach(function(pair) {
            pair = pair.split('=');
            var name = pair[0]
            var value = pair[1]
            if( name.length )
                if (result[name] !== undefined) {
                    if (!result[name].push) {
                        result[name] = [result[name]];
                    }
                    result[name].push(value || '');
                } else {
                    result[name] = value || '';
                }
        });
        return( result );
    }

<a href="index.html?x=1&x=2&x=3&y=blah">something</a>
paramsToJSON("x=1&x=2&x=3&y=blah"); 

console yields => {x: Array[3], y: "blah"} where x is an array as is proper JSON

Sau đó tôi cũng quyết định chuyển đổi nó thành một plugin jQuery ...

$.fn.serializeURLParams = function() {
    var result = {};

    if( !this.is("a") || this.attr("href").indexOf("?") == -1 ) 
        return( result );

    var pairs = this.attr("href").split("?")[1].split('&');
    pairs.forEach(function(pair) {
        pair = pair.split('=');
        var name = decodeURI(pair[0])
        var value = decodeURI(pair[1])
        if( name.length )
            if (result[name] !== undefined) {
                if (!result[name].push) {
                    result[name] = [result[name]];
                }
                result[name].push(value || '');
            } else {
                result[name] = value || '';
            }
    });
    return( result )
}

<a href="index.html?x=1&x=2&x=3&y=blah">something</a>
$("a").serializeURLParams(); 

console yields => {x: Array[3], y: "blah"} where x is an array as is proper JSON

Bây giờ, người đầu tiên sẽ chỉ chấp nhận các tham số nhưng plugin jQuery sẽ lấy toàn bộ url và trả về các tham số được tuần tự hóa.


1

Đây là một cái tôi sử dụng:

var params = {};
window.location.search.substring(1).split('&').forEach(function(pair) {
  pair = pair.split('=');
  if (pair[1] !== undefined) {
    var key = decodeURIComponent(pair[0]),
        val = decodeURIComponent(pair[1]),
        val = val ? val.replace(/\++/g,' ').trim() : '';

    if (key.length === 0) {
      return;
    }
    if (params[key] === undefined) {
      params[key] = val;
    }
    else {
      if ("function" !== typeof params[key].push) {
        params[key] = [params[key]];
      }
      params[key].push(val);
    }
  }
});
console.log(params);

Sử dụng cơ bản, ví dụ.
?a=aa&b=bb
Object {a: "aa", b: "bb"}

Thông số trùng lặp, ví dụ.
?a=aa&b=bb&c=cc&c=potato
Object {a: "aa", b: "bb", c: ["cc","potato"]}

Thiếu chìa khóa, ví dụ.
?a=aa&b=bb&=cc
Object {a: "aa", b: "bb"}

Thiếu giá trị, ví dụ.
?a=aa&b=bb&c
Object {a: "aa", b: "bb"}

Các giải pháp JSON / regex ở trên đưa ra lỗi cú pháp trên url lập dị này:
?a=aa&b=bb&c=&=dd&e
Object {a: "aa", b: "bb", c: ""}


1

Đây là phiên bản nhanh và bẩn của tôi, về cơ bản, nó phân tách các tham số URL được phân tách bằng '&' thành các phần tử mảng và sau đó lặp lại qua mảng đó thêm các cặp khóa / giá trị được phân tách bằng '=' vào một đối tượng. Tôi đang sử dụng decodeURIComponent () để dịch các ký tự được mã hóa thành các chuỗi tương đương bình thường của chúng (vì vậy% 20 trở thành khoảng trắng,% 26 trở thành '&', v.v.):

function deparam(paramStr) {
    let paramArr = paramStr.split('&');     
    let paramObj = {};
    paramArr.forEach(e=>{
        let param = e.split('=');
        paramObj[param[0]] = decodeURIComponent(param[1]);
    });
    return paramObj;
}

thí dụ:

deparam('abc=foo&def=%5Basf%5D&xyz=5')

trả lại

{
    abc: "foo"
    def:"[asf]"
    xyz :"5"
}

Vấn đề duy nhất là xyz là một chuỗi chứ không phải là một số (do sử dụng decodeURIComponent ()), nhưng ngoài ra nó không phải là điểm khởi đầu tồi.


1
//under ES6 
const getUrlParamAsObject = (url = window.location.href) => {
    let searchParams = url.split('?')[1];
    const result = {};
    //in case the queryString is empty
    if (searchParams!==undefined) {
        const paramParts = searchParams.split('&');
        for(let part of paramParts) {
            let paramValuePair = part.split('=');
            //exclude the case when the param has no value
            if(paramValuePair.length===2) {
                result[paramValuePair[0]] = decodeURIComponent(paramValuePair[1]);
            }
        }

    }
    return result;
}

Tôi thực sự thích phương pháp này (năm 2017) so với một số câu trả lời dựa trên regex khác. Nếu polyfill vào mũi tên function (hoặc viết lại như một chức năng truyền thống), tôi nghĩ rằng điều này sẽ làm việc khá tốt qua trình duyệt
Scribblemacher

@Scrippetacher với Babelsự giúp đỡ của bạn, bạn có thể làm tốt điều đó trong môi trường khác
XYz Amos

1

Sử dụng phpjs

function parse_str(str, array) {
  //       discuss at: http://phpjs.org/functions/parse_str/
  //      original by: Cagri Ekin
  //      improved by: Michael White (http://getsprink.com)
  //      improved by: Jack
  //      improved by: Brett Zamir (http://brett-zamir.me)
  //      bugfixed by: Onno Marsman
  //      bugfixed by: Brett Zamir (http://brett-zamir.me)
  //      bugfixed by: stag019
  //      bugfixed by: Brett Zamir (http://brett-zamir.me)
  //      bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/)
  // reimplemented by: stag019
  //         input by: Dreamer
  //         input by: Zaide (http://zaidesthings.com/)
  //         input by: David Pesta (http://davidpesta.com/)
  //         input by: jeicquest
  //             note: When no argument is specified, will put variables in global scope.
  //             note: When a particular argument has been passed, and the returned value is different parse_str of PHP. For example, a=b=c&d====c
  //             test: skip
  //        example 1: var arr = {};
  //        example 1: parse_str('first=foo&second=bar', arr);
  //        example 1: $result = arr
  //        returns 1: { first: 'foo', second: 'bar' }
  //        example 2: var arr = {};
  //        example 2: parse_str('str_a=Jack+and+Jill+didn%27t+see+the+well.', arr);
  //        example 2: $result = arr
  //        returns 2: { str_a: "Jack and Jill didn't see the well." }
  //        example 3: var abc = {3:'a'};
  //        example 3: parse_str('abc[a][b]["c"]=def&abc[q]=t+5');
  //        returns 3: {"3":"a","a":{"b":{"c":"def"}},"q":"t 5"}

  var strArr = String(str)
    .replace(/^&/, '')
    .replace(/&$/, '')
    .split('&'),
    sal = strArr.length,
    i, j, ct, p, lastObj, obj, lastIter, undef, chr, tmp, key, value,
    postLeftBracketPos, keys, keysLen,
    fixStr = function(str) {
      return decodeURIComponent(str.replace(/\+/g, '%20'));
    };

  if (!array) {
    array = this.window;
  }

  for (i = 0; i < sal; i++) {
    tmp = strArr[i].split('=');
    key = fixStr(tmp[0]);
    value = (tmp.length < 2) ? '' : fixStr(tmp[1]);

    while (key.charAt(0) === ' ') {
      key = key.slice(1);
    }
    if (key.indexOf('\x00') > -1) {
      key = key.slice(0, key.indexOf('\x00'));
    }
    if (key && key.charAt(0) !== '[') {
      keys = [];
      postLeftBracketPos = 0;
      for (j = 0; j < key.length; j++) {
        if (key.charAt(j) === '[' && !postLeftBracketPos) {
          postLeftBracketPos = j + 1;
        } else if (key.charAt(j) === ']') {
          if (postLeftBracketPos) {
            if (!keys.length) {
              keys.push(key.slice(0, postLeftBracketPos - 1));
            }
            keys.push(key.substr(postLeftBracketPos, j - postLeftBracketPos));
            postLeftBracketPos = 0;
            if (key.charAt(j + 1) !== '[') {
              break;
            }
          }
        }
      }
      if (!keys.length) {
        keys = [key];
      }
      for (j = 0; j < keys[0].length; j++) {
        chr = keys[0].charAt(j);
        if (chr === ' ' || chr === '.' || chr === '[') {
          keys[0] = keys[0].substr(0, j) + '_' + keys[0].substr(j + 1);
        }
        if (chr === '[') {
          break;
        }
      }

      obj = array;
      for (j = 0, keysLen = keys.length; j < keysLen; j++) {
        key = keys[j].replace(/^['"]/, '')
          .replace(/['"]$/, '');
        lastIter = j !== keys.length - 1;
        lastObj = obj;
        if ((key !== '' && key !== ' ') || j === 0) {
          if (obj[key] === undef) {
            obj[key] = {};
          }
          obj = obj[key];
        } else { // To insert new dimension
          ct = -1;
          for (p in obj) {
            if (obj.hasOwnProperty(p)) {
              if (+p > ct && p.match(/^\d+$/g)) {
                ct = +p;
              }
            }
          }
          key = ct + 1;
        }
      }
      lastObj[key] = value;
    }
  }
}

1

Dựa trên câu trả lời của Mike Causer Tôi đã thực hiện chức năng này để xem xét nhiều tham số có cùng khóa ( foo=bar&foo=baz) và các tham số được phân tách bằng dấu phẩy ( foo=bar,baz,bin). Nó cũng cho phép bạn tìm kiếm một khóa truy vấn nhất định.

function getQueryParams(queryKey) {
    var queryString = window.location.search;
    var query = {};
    var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
    for (var i = 0; i < pairs.length; i++) {
        var pair = pairs[i].split('=');
        var key = decodeURIComponent(pair[0]);
        var value = decodeURIComponent(pair[1] || '');
        // Se possui uma vírgula no valor, converter em um array
        value = (value.indexOf(',') === -1 ? value : value.split(','));

        // Se a key já existe, tratar ela como um array
        if (query[key]) {
            if (query[key].constructor === Array) {
                // Array.concat() faz merge se o valor inserido for um array
                query[key] = query[key].concat(value);
            } else {
                // Se não for um array, criar um array contendo o valor anterior e o novo valor
                query[key] = [query[key], value];
            }
        } else {
            query[key] = value;
        }
    }

    if (typeof queryKey === 'undefined') {
        return query;
    } else {
        return query[queryKey];
    }
}

Ví dụ đầu vào: foo.html?foo=bar&foo=baz&foo=bez,boz,buz&bar=1,2,3

Ví dụ đầu ra

{
    foo: ["bar","baz","bez","boz","buz"],
    bar: ["1","2","3"]
}


1

console.log(decodeURI('abc=foo&def=%5Basf%5D&xyz=5')
  .split('&')
  .reduce((result, current) => {
    const [key, value] = current.split('=');

    result[key] = value;

    return result
  }, {}))


0

FIRST U CẦN THIẾT XÁC ĐỊNH NHỮNG GÌ NHẬN ĐƯỢC:

function getVar()
{
    this.length = 0;
    this.keys = [];
    this.push = function(key, value)
    {
        if(key=="") key = this.length++;
        this[key] = value;
        this.keys.push(key);
        return this[key];
    }
}

Hơn chỉ đọc:

function urlElement()
{
    var thisPrototype = window.location;
    for(var prototypeI in thisPrototype) this[prototypeI] = thisPrototype[prototypeI];
    this.Variables = new getVar();
    if(!this.search) return this;
    var variables = this.search.replace(/\?/g,'').split('&');
    for(var varI=0; varI<variables.length; varI++)
    {
        var nameval = variables[varI].split('=');
        var name = nameval[0].replace(/\]/g,'').split('[');
        var pVariable = this.Variables;
        for(var nameI=0;nameI<name.length;nameI++)
        {
            if(name.length-1==nameI) pVariable.push(name[nameI],nameval[1]);
            else var pVariable = (typeof pVariable[name[nameI]] != 'object')? pVariable.push(name[nameI],new getVar()) : pVariable[name[nameI]];
        }
    }
}

và sử dụng như:

var mlocation = new urlElement();
mlocation = mlocation.Variables;
for(var key=0;key<mlocation.keys.length;key++)
{
    console.log(key);
    console.log(mlocation[mlocation.keys[key]];
}

Vui lòng hợp nhất câu trả lời của bạn. Chỉnh sửa cái khác , sau đó xóa cái này.
Bergi

0

Tôi cũng cần phải xử lý +trong phần truy vấn của URL ( decodeURIComponent không ), vì vậy tôi đã điều chỉnh mã của Wolfgang để trở thành:

var search = location.search.substring(1);
search = search?JSON.parse('{"' + search.replace(/\+/g, ' ').replace(/&/g, '","').replace(/=/g,'":"') + '"}',
             function(key, value) { return key===""?value:decodeURIComponent(value)}):{};

Trong trường hợp của tôi, tôi đang sử dụng jQuery để lấy các tham số biểu mẫu sẵn sàng URL, sau đó mẹo này để xây dựng một đối tượng từ đó và sau đó tôi có thể dễ dàng cập nhật các tham số trên đối tượng và xây dựng lại URL truy vấn, ví dụ:

var objForm = JSON.parse('{"' + $myForm.serialize().replace(/\+/g, ' ').replace(/&/g, '","').replace(/=/g,'":"') + '"}',
             function(key, value) { return key===""?value:decodeURIComponent(value)});
objForm.anyParam += stringToAddToTheParam;
var serializedForm = $.param(objForm);

0

Tôi làm theo cách này:

const uri = new URL('https://example.org/?myvar1=longValue&myvar2=value')
const result = {}
for (let p of uri.searchParams) {
  result[p[0]] = p[1]
}

0

Nếu bạn cần đệ quy, bạn có thể sử dụng thư viện js-extension-ling nhỏ .

npm i js-extension-ling
const jsx = require("js-extension-ling");

console.log(jsx.queryStringToObject("a=1")); 
console.log(jsx.queryStringToObject("a=1&a=3")); 
console.log(jsx.queryStringToObject("a[]=1")); 
console.log(jsx.queryStringToObject("a[]=1&a[]=pomme")); 
console.log(jsx.queryStringToObject("a[0]=one&a[1]=five"));
console.log(jsx.queryStringToObject("http://blabla?foo=bar&number=1234")); 
console.log(jsx.queryStringToObject("a[fruits][red][]=strawberry"));
console.log(jsx.queryStringToObject("a[fruits][red][]=strawberry&a[1]=five&a[fruits][red][]=cherry&a[fruits][yellow][]=lemon&a[fruits][yellow][688]=banana"));

Điều này sẽ tạo ra một cái gì đó như thế này:

{ a: '1' }
{ a: '3' }
{ a: { '0': '1' } }
{ a: { '0': '1', '1': 'pomme' } }
{ a: { '0': 'one', '1': 'five' } }
{ foo: 'bar', number: '1234' }
{
  a: { fruits: { red: { '0': 'strawberry' } } }
}
{
  a: {
    '1': 'five',
    fruits: {
      red: { '0': 'strawberry', '1': 'cherry' },
      yellow: { '0': 'lemon', '688': 'banana' }
    }
  }
}

Lưu ý: nó dựa trên hàm parse_str của locutus ( https://locutus.io/php/strings/parse_str/ ).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.