Converti i parametri URL in un object JavaScript

Ho una stringa come questa:

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

Come posso convertirlo in un object JavaScript come questo?

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

    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

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

    • decodeURI: abc = foo & def = [asf] e xyz = 5
    • Citazioni di fuga: stesso, in quanto non ci sono citazioni
    • Sostituisci &: abc=foo","def=[asf]","xyz=5
    • Replace =: abc":"foo","def":"[asf]","xyz":"5
    • Suround con curli e virgolette: {"abc":"foo","def":"[asf]","xyz":"5"}

    che è legale JSON.

    Una soluzione migliorata consente più caratteri nella stringa di ricerca. Usa 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

    Un unico rivestimento:

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

    Dividi su & per ottenere coppie nome / valore, quindi dividi ogni coppia su = . 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 le espressioni regolari:

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

    Questo è adattato da “Ricerca e non sostituire” di John Resig.

    Questa è la versione semplice, ovviamente ti consigliamo di aggiungere un 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]); } 

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

    Ho avuto lo stesso problema, ho provato le soluzioni qui, ma nessuno di loro ha funzionato veramente, dal momento 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 una matrice di param 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; } 

    Un’altra soluzione basata sullo standard più recente 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 prega di notare che questa soluzione sta facendo uso di

    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 semplicità.

    Dovrebbe essere facile creare una soluzione più compatibile poiché si ha accesso a iteratore searchParams.entries () .

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

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

    Non ci sono soluzioni native di cui sono a conoscenza. Dojo ha un metodo di unserializzazione incorporato se usi questa struttura per caso.

    Altrimenti puoi implementarlo tu stesso 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 ()

    C’è una libreria leggera chiamata YouAreI.js che è stata testata e rende questo 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' } 

    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 object 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 effettivamente:

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

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

    Params duplicati, 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, es.
    ?a=aa&b=bb&c
    Object {a: "aa", b: "bb"}

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

    Ecco la mia versione veloce e sporca, in pratica la sua suddivisione dei parametri URL separati da “&” in elementi di array, e quindi itera su quell’array aggiungendo coppie chiave / valore separate da “=” in un object. Sto usando decodeURIComponent () per tradurre i caratteri codificati ai loro equivalenti di stringa normali (così% 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 brutto punto di partenza.

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

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

    ES6 una fodera. Pulito e semplice

     var obj = Array.from(new URLSearchParams(location.search).keys()).reduce((sum, value,index,arr)=>{ return Object.assign({[value]: new URLSearchParams(location.search).get(value)}, sum); }, {}); 

    Piuttosto facile con l’API Web JavaScript di URLSearchParams ,

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

    IL PRIMO U NECESSARIO DEFINIRE QUELLO CHE È UN VICE:

     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 

    e usare come:

     var mlocation = new urlElement(); mlocation = mlocation.Variables; for(var key=0;key 

    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 ); } something 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 ) } something $("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.

    Avevo bisogno di trattare anche con + nella 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 parametri di modulo pronti per l’URL, quindi questo trucco per creare un object e posso quindi aggiornare facilmente i parametri sull’object e ribuild 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); 

    Basandosi 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 i 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 eo 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"] }