Come convertire i parametri URL in un oggetto JavaScript?


223

Ho una stringa come questa:

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

Come posso convertirlo in un oggetto JavaScript come questo?

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


1
Non è: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/… developer.mozilla.org/en-US/docs/Web/API/URL/… (anche se dovremo aspettare un ancora un po 'di più perché tutti i browser lo abbiano rilevato)
Arthur,

Risposte:


335

modificare

Questa modifica migliora e spiega la risposta in base ai commenti.

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

Esempio

Analizza abc=foo&def=%5Basf%5D&xyz=5in cinque passaggi:

  • decodeURI: abc = foo & def = [asf] & xyz = 5
  • Virgolette di escape: stesso, in quanto non ci sono virgolette
  • Sostituisci e: abc=foo","def=[asf]","xyz=5
  • Sostituisci =: abc":"foo","def":"[asf]","xyz":"5
  • Circondato con ricci e citazioni: {"abc":"foo","def":"[asf]","xyz":"5"}

che è legale JSON.

Una soluzione migliorata consente più caratteri nella stringa di ricerca. Utilizza una funzione reviver per la decodifica URI:

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

Esempio

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

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

Risposta originale

Una fodera:

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

4
Affinché funzioni in CoffeeScript, sfuggire a '=' nella regex. .replace (/ \ = / g, "\": \ "")
airlok,

175
Non è un one-liner ... è una stazione spaziale.
Ziggy,

5
meglio se usiJSON.parse('{"' + decodeURI(location.search.substring(1).replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
Daniël Tulp

4
Questo non riesce se hai un carattere di segno uguale nell'URL da analizzare. ES: "cookie = dlksdlfj = sodkfjhsdlfj"
jholloman,

3
Inoltre non funziona quando si dispone di uno dei parametri senza valore.
Sych,

113

2020 ES6 / 7/8 e in avvicinamento

A partire da ES6 e successivi, Javascript offre diversi costrutti per creare una soluzione performante per questo problema.

Ciò include l'utilizzo di URLSearchParams e iteratori

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

Se il tuo caso d'uso richiede di convertirlo effettivamente in oggetto, puoi implementare la seguente funzione:

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 di base

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

Utilizzo di Object.fromEntries e spread

Possiamo usare Object.fromEntries (che è attualmente nella fase 4), sostituendolo paramsToObjectcon Object.fromEntries(entries).

Le coppie di valori su cui scorrere le coppie nome-valore dell'elenco con la chiave come nome e il valore come valore.

Da allora URLParams, restituisce un oggetto iterabile , l'uso dell'operatore spread invece di chiamare .entriesprodurrà anche voci secondo le sue specifiche:

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

Nota: tutti i valori sono automaticamente stringhe secondo le specifiche URLSearchParams

Stesse chiavi multiple

Come sottolineato da @siipe , le stringhe contenenti più valori della stessa chiave verranno costrette all'ultimo valore disponibile: foo=first_value&foo=second_valuediventerà in sostanza:{foo: "second_value"} .

Secondo questa risposta: https://stackoverflow.com/a/1746566/1194694 non ci sono specifiche per decidere cosa farne e ogni framework può comportarsi diversamente.

Un caso d'uso comune sarà quello di unire gli stessi due valori in un array, trasformando l'oggetto di output in:

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

Ciò può essere ottenuto con il seguente codice:

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
Non consiglio questa soluzione. URLSearchParams ha specifiche illogiche ( developer.mozilla.org/en-US/docs/Web/API/… )
Seph Reed

1
Mi dispiace ma la logica non ha nulla a che fare con esso. Si potrebbe obiettare che si tratta di un search stringparser - che è ciò per cui è stato progettato, indipendentemente dal fatto che sia associato a un URL
silicakes

Object.fromEntriesnon funziona per tasti ripetuti. Se proviamo a fare qualcosa del genere ?foo=bar1&foo=bar2, otterremo solo { foo: 'bar2' }. L'oggetto richiesta Node.js, ad esempio, lo analizza come{ foo: ['bar1', 'bar2'] }
Siipe il

Hai ragione, ma questo non ha specifiche e molte lingue adottare un approccio supponente di come si analizzarlo: stackoverflow.com/a/1746566/1194694
silicakes

Questo mi sembra buono, ma per ottenere i valori della chiave ripetitiva possiamo usare questo let temp={};Object.keys(params).map(key=>{temp[key]=urlParams.getAll(key)})
Tirumaleshwar Keregadde

45

ES6 una fodera. Pulito e semplice.

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

Per il tuo caso specifico, sarebbe:

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


Questo cade preda dei gotchas. "http://place.com?foo=bar&hello=%40world&showThing"produce{ hello: "@world", http://place.com?foo: "bar", showThing: "" }
Seph Reed,

1
Dovresti usarlo con una stringa di query (da location.search) come "foo = bar & hello =% 40world & showThing" non l'intero URL, come suggerisce la domanda.
polli,

1
Questo può essere usato, ma con cautela ?someValue=falsediventa{ someValue: "false" }
Simon,

Non funziona per tasti ripetuti. Se proviamo a fare qualcosa del genere ?foo=bar1&foo=bar2, otterremo solo { foo: 'bar2' }. L'oggetto richiesta Node.js lo analizza come{ foo: ['bar1', 'bar2'] }
Siipe,

@SephReed, credo che il tuo commento sia indirizzato alla versione aggiornata che utilizzalocation.search
KyleMit

27

Dividi &per ottenere coppie nome / valore, quindi dividi ciascuna coppia =. Ecco un esempio:

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

Un altro approccio, usando espressioni regolari:

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

Questo è adattato da "Cerca e non sostituire" di John Resig .


tx! dovresti anche aggiungere decodeURIComponen (p [0]) a sinistra :)
Alex,

Il primo esempio non funziona con una stringa di query vuota.
Michał Perłakowski,

18

Una soluzione concisa:

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

questo fallisce con le matrici cioè: x = 1 & x = 2
Sh eldeeb

16

Le soluzioni proposte che ho trovato finora non coprono scenari più complessi.

Avevo bisogno di convertire una stringa di query come

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

in un oggetto come:

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

O:

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

IN:

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

Ho compilato e adattato più soluzioni in una che funziona davvero:

CODICE:

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

Questa è la risposta migliore, in quanto gestisce effettivamente query complesse.
Georgy Ivanov,

Penso che questo complica solo le cose, vorrei solo passare obj=encodeURIComponent(JSON.stringify({what:{ever:','},i:['like']})).
polli

15

Questa è la versione semplice, ovviamente vorrai aggiungere qualche controllo degli errori:

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

1
Non hai dimenticato di decodificare la stringa per convertire% 5B e% 5D in caratteri?
jfriend00,

@Alex - Hai usato il codice aggiornato o l'originale? L'originale aveva un problema e un refuso.
Justin Niessner,

Non è in grado di gestire correttamente i parametri quando i loro valori contengono '='. Taglia i valori al primo '='.
Greck,

JSON.parse('{"' + decodeURIComponent(query.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'));funziona per me
Danil Gaponov,

1
non funziona name[]=test1&name[]=test2e si tradurrà inname[]=test2
Rafee

10

Ho trovato $ .String.deparam la soluzione pre-costruita più completa (può fare oggetti nidificati ecc.). Consulta la documentazione .


sottolineando solo se l'input sarà sempre una stringa di query serializzata, non è necessario preoccuparsi di annidamento e una soluzione più leggera è probabilmente migliore
mattacolare

Beh, certo ... ma è già stato fatto e testato (Justin, ad esempio, dimentica la decodifica dell'URI nella risposta iniziale - che sono piccoli problemi che possono rendere le cose molto più complesse di quanto sembrino inizialmente).
Daff,

9

2019 One-Liner Approach

Per il tuo caso specifico:

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

Per il caso più generico in cui qualcuno vuole analizzare i parametri di query su un oggetto:

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

Se non riesci a utilizzare Object.fromEntries, funzionerà anche:

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

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

1
URLSearchParams ha alcuni trucchi per cui questo si rompe. "http://place.com?foo=bar&hello=%40world&showThingproduce { hello: "@world", http://place.com?foo: "bar", showThing: "" }. Prova ad aggiungerestr.split("?").pop()
Seph Reed,

7

Un'altra soluzione basata sull'ultimo standard di 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()))
    : {};
}

Si noti che questa soluzione sta utilizzando

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

e _.fromPairs ( https://lodash.com/docs#fromPairs ) di lodash per motivi di semplicità.

Dovrebbe essere facile creare una soluzione più compatibile poiché hai accesso all'iterer searchParams.entries () .


6

Ho avuto lo stesso problema, ho provato le soluzioni qui, ma nessuna di queste ha funzionato davvero, dato che avevo array nei parametri URL, come questo:

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

Così ho finito per scrivere la mia funzione JS, che rende un array fuori dal parametro in 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
Questo è stato davvero utile e ha fatto quasi esattamente quello che volevo. Non mi è piaciuto, tuttavia, come "[]" venga mantenuto in contatto nell'oggetto se i parametri URL sono simili: bacon [] = eggs & bacon [] = toast. Quindi ho aggiunto una riga dopo if(chunk[0].search("\\[\\]") !== -1) {che èchunk[0]=chunk[0].replace(/\[\]$/,'');
rgbflawed

@rgbflawed dovresti modificare la risposta per il bene del futuro lettore e leggibilità
Webwoman

Usa constinvece varperché qualcuno potrebbe fare createObjFromURI = 'some text'e quindi farebbe confusione con il codice. se lo usi, constqualcuno in esecuzione createObjFromURI = 'some text'commetterà un errore e non potrà assegnare valore alla variabile costante.
Justin Liu,

5

Utilizzo di ES6, API URL e 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 one liner (se possiamo chiamarlo in questo modo vedendo la linea lunga)

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


2
È inoltre possibile destrutturare curper maggiore chiarezza. .reduce((prev, [key, val]) => {prev[key] = val})
Allan Lei,

mi piace il tuo suggerimento Allan Lei. Aggiornamento la mia risposta
fadomire

3

Abbastanza facile usando l' 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());

link utili

NOTA : non supportato in IE


3

Per Node JS, è possibile utilizzare l'API JS Node querystring:

const querystring = require('querystring');

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

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


2

Non esiste una soluzione nativa di cui sia a conoscenza. Dojo ha un metodo di serializzazione incorporato se si utilizza quel framework per caso.

Altrimenti puoi implementarlo da solo piuttosto semplicemente:

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

modifica: aggiunto decodeURIComponent ()


2

C'è una libreria leggera chiamata YouAreI.js che è stata testata e rende tutto molto semplice.

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

Uno dei modi più semplici per farlo utilizzando l'interfaccia URLSearchParam.

Di seguito è riportato lo snippet di codice funzionante:

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

Questa sembra essere la soluzione migliore in quanto prende in considerazione più parametri con lo stesso nome.

    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

In seguito ho deciso di convertirlo anche in un 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

Ora, il primo accetterà solo i parametri ma il plugin jQuery prenderà l'intero url e restituirà i parametri serializzati.


1

Eccone uno che uso:

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

Utilizzo di base, ad es.
?a=aa&b=bb
Object {a: "aa", b: "bb"}

Parametri duplicati, ad es.
?a=aa&b=bb&c=cc&c=potato
Object {a: "aa", b: "bb", c: ["cc","potato"]}

Chiavi mancanti, ad es.
?a=aa&b=bb&=cc
Object {a: "aa", b: "bb"}

Valori mancanti, ad es.
?a=aa&b=bb&c
Object {a: "aa", b: "bb"}

Le precedenti soluzioni JSON / regex generano un errore di sintassi su questo url stravagante:
?a=aa&b=bb&c=&=dd&e
Object {a: "aa", b: "bb", c: ""}


1

Ecco la mia versione veloce e sporca, fondamentalmente la suddivisione dei parametri URL separati da '&' in elementi di array, e quindi scorre su quell'array aggiungendo coppie chiave / valore separate da '=' in un oggetto. Sto usando decodeURIComponent () per tradurre i caratteri codificati nei loro equivalenti stringa normali (quindi% 20 diventa uno spazio,% 26 diventa '&', ecc.):

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

esempio:

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

ritorna

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

L'unico problema è che xyz è una stringa e non un numero (a causa dell'uso di decodeURIComponent ()), ma oltre a ciò non è un cattivo punto di partenza.


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

Mi piace molto questo metodo (nel 2017) rispetto ad alcune delle altre risposte basate su regex. Se esegui il polifillamento della funzione freccia (o riscrivi come una funzione tradizionale), penso che dovrebbe funzionare abbastanza bene tra i browser
Scribblemacher,

@Scribblemacher con l Babel'aiuto puoi farlo bene in altri ambienti
XYz Amos,

1

Utilizzando 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

Basandomi sulla risposta di Mike Causer, ho creato questa funzione che prende in considerazione più parametri con lo stesso tasto ( foo=bar&foo=baz) e anche parametri separati da virgola ( foo=bar,baz,bin). Ti consente anche di cercare una determinata chiave di query.

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

Esempio di input: foo.html?foo=bar&foo=baz&foo=bez,boz,buz&bar=1,2,3

Esempio di output

{
    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

LA PRIMA U DEVE DEFINIRE COS'È UN OTTENERE 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];
    }
}

Di appena letto:

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

e usare come:

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

Unisci le tue risposte. Modifica l'altro , quindi elimina questo.
Bergi,

0

Avevo bisogno di occuparmi anche +della parte di query dell'URL ( decodeURIComponent no ), quindi ho adattato il codice di Wolfgang per diventare:

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

Nel mio caso, sto usando jQuery per ottenere i parametri del modulo pronti per l'URL, quindi questo trucco per costruire un oggetto da esso e posso quindi facilmente aggiornare i parametri sull'oggetto e ricostruire l'URL della query, ad esempio:

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

Lo faccio in questo modo:

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

Se hai bisogno di ricorsione, puoi usare la piccola libreria 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"));

Questo produrrà qualcosa del genere:

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

Nota: si basa sulla funzione locutus parse_str ( https://locutus.io/php/strings/parse_str/ ).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.