Bagaimana cara mengonversi parameter URL ke objek JavaScript?

223

Saya memiliki string seperti ini:

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

Bagaimana saya bisa mengubahnya menjadi objek JavaScript seperti ini?

{
  abc: 'foo',
  def: '[asf]',
  xyz: 5
}
Alex
sumber
1
Bukan: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/… developer.mozilla.org/en-US/docs/Web/API/URL/… (meskipun kita harus menunggu sebentar lagi untuk semua browser telah mengambil ini)
Arthur

Jawaban:

334

Edit

Hasil edit ini meningkatkan dan menjelaskan jawaban berdasarkan komentar.

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

Contoh

Parsing abc=foo&def=%5Basf%5D&xyz=5dalam lima langkah:

  • decodeURI: abc = foo & def = [asf] & xyz = 5
  • Kutipan melarikan diri: sama, karena tidak ada kutipan
  • Ganti &: abc=foo","def=[asf]","xyz=5
  • Ganti =: abc":"foo","def":"[asf]","xyz":"5
  • Penuh dengan ikal dan kutipan: {"abc":"foo","def":"[asf]","xyz":"5"}

yang merupakan JSON legal.

Sebuah solusi ditingkatkan memungkinkan untuk karakter lebih dalam string pencarian. Ini menggunakan fungsi reviver untuk decoding URI:

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

Contoh

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

memberi

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

Jawaban asli

Satu kalimat:

JSON.parse('{"' + decodeURI("abc=foo&def=%5Basf%5D&xyz=5".replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}')
Wolfgang Kuehn
sumber
4
Agar ini bekerja di CoffeeScript, lepas '=' di regex. .replace (/ \ = / g, "\": \ "")
airlok
175
Itu bukan satu kalimat ... itu stasiun ruang angkasa.
Ziggy
5
lebih baik jika Anda menggunakanJSON.parse('{"' + decodeURI(location.search.substring(1).replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
Daniël Tulp
4
Ini gagal jika Anda memiliki karakter tanda sama dengan di url untuk diuraikan. EX: "cookie = dlksdlfj = sodkfjhsdlfj"
jholloman
3
Juga tidak berfungsi ketika Anda memiliki salah satu parameter tanpa nilai.
Sych
113

ES6 / 7/8 2020 dan tentang pendekatan

Mulai ES6 dan seterusnya, Javascript menawarkan beberapa konstruksi untuk membuat solusi yang tepat untuk masalah ini.

Ini termasuk menggunakan URLSearchParams dan iterator

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

Jika use case Anda mengharuskan Anda untuk benar-benar mengubahnya menjadi objek, Anda dapat mengimplementasikan fungsi berikut:

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 Dasar

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

Menggunakan Object.fromEntries dan menyebar

Kita bisa menggunakan Object.fromEntries (yang saat ini dalam tahap 4), ganti paramsToObjectdengan Object.fromEntries(entries).

Pasangan nilai yang akan diulangi adalah pasangan daftar nama-nilai dengan kuncinya adalah nama dan nilainya sebagai nilainya.

Karena URLParams, mengembalikan objek yang dapat diulang , menggunakan operator spread alih-alih memanggil .entriesjuga akan menghasilkan entri per specnya:

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

Catatan: Semua nilai adalah string secara otomatis sesuai dengan spesifikasi URLSearchParams

Beberapa kunci yang sama

Sebagai @siipe ditunjukkan , string yang berisi beberapa nilai kunci yang sama akan dipaksa ke nilai terakhir yang tersedia: foo=first_value&foo=second_valuepada dasarnya akan menjadi:{foo: "second_value"} .

Sesuai jawaban ini: https://stackoverflow.com/a/1746566/1194694 tidak ada spesifikasi untuk memutuskan apa yang harus dilakukan dengannya dan setiap kerangka kerja dapat berperilaku berbeda.

Kasus penggunaan umum adalah menggabungkan dua nilai yang sama ke dalam array, membuat objek output menjadi:

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

Ini dapat dicapai dengan kode berikut:

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}
silicakes
sumber
2
Saya tidak merekomendasikan solusi ini. URLSearchParams memiliki spesifikasi yang tidak masuk akal ( developer.mozilla.org/en-US/docs/Web/API/… )
Seph Reed
1
Maaf, tetapi logika tidak ada hubungannya dengan itu. Orang mungkin berpendapat bahwa itu adalah search stringpengurai - yang memang dirancang untuk dilakukan, terlepas dari apa yang dikaitkan dengan URL
silicakes
Object.fromEntriestidak berfungsi untuk kunci yang berulang. Jika kita mencoba melakukan sesuatu seperti ?foo=bar1&foo=bar2, kita hanya akan mendapatkannya { foo: 'bar2' }. Objek permintaan Node.js, misalnya, mem{ foo: ['bar1', 'bar2'] }
parsingnya
Anda benar, namun ini tidak memiliki spek dan banyak bahasa menggunakan pendekatan yang
disarankan tentang
Ini terlihat bagus untuk saya, tetapi untuk mendapatkan nilai untuk kunci berulang kita dapat menggunakan ini let temp={};Object.keys(params).map(key=>{temp[key]=urlParams.getAll(key)})
Tirumaleshwar Keregadde
45

ES6 satu liner. Bersih dan sederhana.

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

Untuk kasus spesifik Anda, itu akan menjadi:

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

ayam
sumber
Ini menjadi mangsa para gotcha. "http://place.com?foo=bar&hello=%40world&showThing"menghasilkan{ hello: "@world", http://place.com?foo: "bar", showThing: "" }
Seph Reed
1
Anda harus menggunakannya dengan string kueri (dari location.search) seperti "foo = bar & hello =% 40world & showThing" bukan keseluruhan url, seperti yang disarankan pertanyaan.
ayam
1
Ini dapat digunakan, tetapi dengan hati-hati ?someValue=falsemenjadi{ someValue: "false" }
Simon
Ini tidak berfungsi untuk kunci yang diulang. Jika kita mencoba melakukan sesuatu seperti ?foo=bar1&foo=bar2, kita hanya akan mendapatkannya { foo: 'bar2' }. Node.js meminta objek mem{ foo: ['bar1', 'bar2'] }
parsingnya
@SephReed, saya yakin komentar Anda ditujukan dengan versi terbaru yang menggunakanlocation.search
KyleMit
27

Pisahkan &untuk mendapatkan pasangan nama / nilai, lalu pisahkan setiap pasangan =. Ini sebuah contoh:

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

Pendekatan lain, menggunakan ekspresi reguler:

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

Ini diadaptasi dari "Cari dan Jangan Ganti" John Resig .

Wayne
sumber
tx! Anda juga harus menambahkan decodeURIComponen (p [0]) di sebelah kiri :)
Alex
Contoh pertama tidak berfungsi dengan string kueri kosong.
Michał Perłakowski
18

Solusi ringkas:

location.search
  .slice(1)
  .split('&')
  .map(p => p.split('='))
  .reduce((obj, pair) => {
    const [key, value] = pair.map(decodeURIComponent);
    return ({ ...obj, [key]: value })
  }, {});
Clemens Helm
sumber
ini gagal dengan array yaitu: x = 1 & x = 2
Sh eldeeb
16

Solusi yang saya temukan sejauh ini tidak mencakup skenario yang lebih kompleks.

Saya perlu mengonversi string kueri seperti

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

menjadi objek seperti:

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

ATAU:

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

KE:

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

Saya mengkompilasi dan mengadaptasi beberapa solusi menjadi solusi yang benar-benar berfungsi:

KODE:

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;
};
Mauricio van der Maesen
sumber
Ini adalah jawaban terbaik, karena memang benar menangani pertanyaan kompleks.
Georgy Ivanov
Saya pikir ini hanya mempersulit, saya baru saja lulus obj=encodeURIComponent(JSON.stringify({what:{ever:','},i:['like']})).
ayam
15

Ini adalah versi sederhana, jelas Anda ingin menambahkan beberapa pengecekan kesalahan:

var obj = {};
var pairs = queryString.split('&');
for(i in pairs){
    var split = pairs[i].split('=');
    obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}
Justin Niessner
sumber
1
Tidakkah Anda lupa untuk melepaskan kode string untuk mengubah% 5B dan% 5D ke karakter?
jfriend00
@Alex - Apakah Anda menggunakan kode yang diperbarui atau yang asli? Asli memiliki satu masalah dan salah ketik.
Justin Niessner
Itu tidak bisa menangani params dengan benar ketika nilainya mengandung '='. Ini memangkas nilai menjadi yang pertama '='.
Greck
JSON.parse('{"' + decodeURIComponent(query.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'));bekerja untuk saya
Danil Gaponov
1
itu tidak bekerja untuk name[]=test1&name[]=test2dan itu akan menghasilkanname[]=test2
Rafee
10

Saya menemukan $ .String.deparam solusi pra dibangun paling lengkap (dapat melakukan objek bersarang dll). Lihatlah dokumentasinya .

Daff
sumber
hanya menunjukkan jika input Anda akan selalu menjadi string kueri berseri, tidak perlu khawatir tentang bersarang dan solusi yang lebih ringan mungkin lebih baik
mattacular
Yah tentu saja ... tetapi sudah dilakukan dan diuji (Justin misalnya lupa untuk memecahkan kode URI di jawaban awal - yang merupakan masalah kecil yang dapat membuat hal-hal menjadi jauh lebih kompleks daripada yang tampak pada awalnya).
Daff
9

Pendekatan One-Liner 2019

Untuk kasus spesifik Anda:

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

Untuk kasus yang lebih umum di mana seseorang ingin mem-parsing kueri param ke objek:

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

Jika Anda tidak dapat menggunakan Object.fromEntries, ini juga akan berfungsi:

Array.from(new URLSearchParams(window.location.search)).reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
David Hansen
sumber
Juga[...new URLSearchParams(window.location.search)].reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
dman
1
URLSearchParams memiliki beberapa Gotcha yang ingin dipecahkan. "http://place.com?foo=bar&hello=%40world&showThingmenghasilkan { hello: "@world", http://place.com?foo: "bar", showThing: "" }. Coba tambahkanstr.split("?").pop()
Seph Reed
7

Solusi lain berdasarkan standar terbaru dari 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()))
    : {};
}

Harap dicatat bahwa solusi ini memanfaatkan

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

dan _.fromPairs ( https://lodash.com/docs#fromPairs ) lodash demi kesederhanaan.

Seharusnya mudah untuk membuat solusi yang lebih kompatibel karena Anda memiliki akses ke iterator searchParams.entries () .

Nickey
sumber
6

Saya memiliki masalah yang sama, mencoba solusinya di sini, tetapi tidak ada yang benar-benar berfungsi, karena saya memiliki array dalam parameter URL, seperti ini:

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

Jadi saya akhirnya menulis fungsi JS saya sendiri, yang membuat array dari param di 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;
}
pcigler
sumber
2
Ini sangat membantu dan melakukan hampir apa yang saya inginkan. Namun, saya tidak suka bagaimana "[]" disimpan dalam objek jika parameter URLnya seperti: bacon [] = telur & bacon [] = roti panggang. Jadi saya menambahkan dalam satu baris setelah if(chunk[0].search("\\[\\]") !== -1) {ituchunk[0]=chunk[0].replace(/\[\]$/,'');
rgbflawed
@rgbflawed Anda harus mengedit jawaban demi pembaca dan keterbacaan di masa depan
Webwoman
Gunakan constalih-alih varkarena seseorang mungkin melakukannya createObjFromURI = 'some text'dan mereka akan mengacaukan kodenya. jika Anda menggunakan constmaka seseorang yang menjalankan createObjFromURI = 'some text'akan membuat kesalahan tidak dapat memberikan nilai ke variabel konstan.
Justin Liu
5

Menggunakan ES6, URL API dan URLSearchParams API.

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;
}
supergentle
sumber
5

ES6 one liner (jika kita bisa menyebutnya dengan cara melihat garis panjang)

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

fadomire
sumber
2
Anda juga dapat merusaknya curuntuk beberapa kejelasan tambahan. .reduce((prev, [key, val]) => {prev[key] = val})
Allan Lei
Saya suka saran Anda, Allan Lei. Saya memperbarui jawaban saya
fadomire
3

Cukup mudah menggunakan 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());

Tautan yang Berguna

CATATAN : Tidak Didukung di IE

Erisan Olasheni
sumber
3

Untuk Node JS, Anda dapat menggunakan Node JS API querystring:

const querystring = require('querystring');

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

Dokumentasi: https://nodejs.org/api/querystring.html

etoksin
sumber
2

Tidak ada solusi asli yang saya ketahui. Dojo memiliki metode unserialisasi bawaan jika Anda menggunakan kerangka kerja itu secara kebetulan.

Kalau tidak, Anda bisa menerapkannya sendiri cukup sederhana:

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

sunting: tambah komponen decodeURICon ()

tidak biasa
sumber
2

Ada perpustakaan ringan bernama YouAreI.js yang diuji dan membuatnya sangat mudah.

YouAreI = require('YouAreI')
uri = new YouAreI('http://user:[email protected]:3000/a/b/c?d=dad&e=1&f=12.3#fragment');

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

Salah satu cara paling sederhana untuk melakukan ini menggunakan antarmuka URLSearchParam.

Berikut ini cuplikan kode kerja:

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;
   });
Rishu Ranjan
sumber
1

Ini tampaknya menjadi solusi terbaik karena perlu mempertimbangkan beberapa parameter dengan nama yang sama.

    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

Saya kemudian memutuskan untuk mengubahnya menjadi plugin jQuery juga ...

$.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

Sekarang, yang pertama hanya akan menerima parameter tetapi plugin jQuery akan mengambil seluruh url dan mengembalikan parameter serial.

jQuery Junkie
sumber
1

Inilah yang saya gunakan:

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

Penggunaan dasar, mis.
?a=aa&b=bb
Object {a: "aa", b: "bb"}

Duplikat params, mis.
?a=aa&b=bb&c=cc&c=potato
Object {a: "aa", b: "bb", c: ["cc","potato"]}

Kunci tidak ada, mis.
?a=aa&b=bb&=cc
Object {a: "aa", b: "bb"}

Nilai yang hilang, mis.
?a=aa&b=bb&c
Object {a: "aa", b: "bb"}

Solusi JSON / regex di atas melempar kesalahan sintaks pada url aneh ini:
?a=aa&b=bb&c=&=dd&e
Object {a: "aa", b: "bb", c: ""}

Mike Causer
sumber
1

Inilah versi cepat dan kotor saya, yang pada dasarnya memisahkan parameter URL yang dipisahkan oleh '&' menjadi elemen array, dan kemudian beralih ke array itu dengan menambahkan pasangan kunci / nilai yang dipisahkan oleh '=' ke dalam objek. Saya menggunakan komponen decodeURICon () untuk menerjemahkan karakter yang disandikan ke string normal mereka (jadi% 20 menjadi spasi,% 26 menjadi '&', dll):

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

contoh:

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

kembali

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

Satu-satunya masalah adalah bahwa xyz adalah string dan bukan angka (karena menggunakan dekodeURkomponen ()), tetapi di luar itu bukan titik awal yang buruk.

Eric
sumber
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;
}
XYz Amos
sumber
Saya sangat suka metode ini (pada 2017) dibandingkan dengan beberapa jawaban berbasis regex lainnya. Jika polyfill fungsi panah (atau menulis ulang sebagai fungsi tradisional), saya pikir ini akan bekerja dengan cukup baik lintas-browser
Scribblemacher
@Scribblemacher dengan Babelbantuan Anda dapat melakukannya dengan baik di bawah lingkungan lain
XYz Amos
1

Menggunakan 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;
    }
  }
}
Duy Hoang
sumber
1

Membangun di atas jawaban Mike Causer Saya telah membuat fungsi ini yang mempertimbangkan beberapa params dengan kunci yang sama ( foo=bar&foo=baz) dan juga parameter yang dipisahkan koma ( foo=bar,baz,bin). Ini juga memungkinkan Anda mencari kunci permintaan tertentu.

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

Input contoh: foo.html?foo=bar&foo=baz&foo=bez,boz,buz&bar=1,2,3

Contoh output

{
    foo: ["bar","baz","bez","boz","buz"],
    bar: ["1","2","3"]
}
Gus
sumber
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
  }, {}))

aagamezl
sumber
0

U PERTAMA PERLU MENDAFTARKAN APA YANG DAPATKAN VAR:

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

Dari sekadar membaca:

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

dan gunakan seperti:

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]];
}
Ag.
sumber
Harap gabungkan jawaban Anda. Edit yang lain , lalu hapus yang ini.
Bergi
0

Saya perlu juga berurusan dengan +di bagian permintaan URL ( decodeURIComponent tidak ), jadi saya mengadaptasi kode Wolfgang menjadi:

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

Dalam kasus saya, saya menggunakan jQuery untuk mendapatkan parameter bentuk URL-ready, maka trik ini untuk membangun objek dari itu dan saya kemudian dapat dengan mudah memperbarui parameter pada objek dan membangun kembali URL kueri, misalnya:

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);
dlauzon
sumber
0

Saya melakukannya dengan cara ini:

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

sumber
0

Jika Anda membutuhkan rekursi, Anda dapat menggunakan perpustakaan kecil js-extension-ling .

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

Ini akan menampilkan sesuatu seperti ini:

{ 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' }
    }
  }
}

Catatan: ini didasarkan pada fungsi locutus parse_str ( https://locutus.io/php/strings/parse_str/ ).

ling
sumber