valores recorrer objetos objeto metodos lista funciones ejemplos añadir array agregar javascript jquery url url-parameters url-parsing

recorrer - objetos en javascript



Convierta parámetros de URL a un objeto de JavaScript (20)

Tengo una cadena como esta:

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

¿Cómo puedo convertirlo en un objeto de JavaScript como este?

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


Editar

Esta edición mejora y explica la respuesta en función de los comentarios.

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

Ejemplo

Parse abc=foo&def=%5Basf%5D&xyz=5 en cinco pasos:

  • decodeURI: abc = foo & def = [asf] & xyz = 5
  • Frases de escape: lo mismo, ya que no hay citas
  • Reemplazar &: abc=foo","def=[asf]","xyz=5
  • Reemplazar =: abc":"foo","def":"[asf]","xyz":"5
  • Suround con curlies y comillas: {"abc":"foo","def":"[asf]","xyz":"5"}

que es JSON legal

Una solución mejorada permite más caracteres en la cadena de búsqueda. Utiliza una función reviver para la decodificación URI:

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

Ejemplo

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

da

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

Respuesta original

Un trazador de líneas:

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


Aquí está mi versión rápida y sucia, básicamente es dividir los parámetros de URL separados por ''&'' en elementos de matriz, y luego itera sobre esa matriz agregando pares clave / valor separados por ''='' en un objeto. Estoy usando decodeURIComponent () para traducir los caracteres codificados a sus equivalentes de cadena normales (por lo que% 20 se convierte en un espacio,% 26 se convierte en ''&'', etc.):

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

ejemplo:

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

devoluciones

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

El único problema es que xyz es una cadena y no un número (debido a que usa decodeURIComponent ()), pero más allá de eso no es un mal punto de partida.


Aquí hay uno que 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);

Uso básico, ej.
?a=aa&b=bb
Object {a: "aa", b: "bb"}

Parámetros duplicados, ej.
?a=aa&b=bb&c=cc&c=potato
Object {a: "aa", b: "bb", c: ["cc","potato"]}

Teclas faltantes, ej.
?a=aa&b=bb&=cc
Object {a: "aa", b: "bb"}

Faltan valores, ej.
?a=aa&b=bb&c
Object {a: "aa", b: "bb"}

Las soluciones JSON / regex anteriores arrojan un error de sintaxis en esta url loca:
?a=aa&b=bb&c=&=dd&e
Object {a: "aa", b: "bb", c: ""}


Dividir en & para obtener pares de nombre / valor, luego dividir cada par en = . Aquí hay un ejemplo:

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

Otro enfoque, usando expresiones regulares:

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

Esto está adaptado de John Resig, "Buscar y no reemplazar" .


ES6 one liner. Limpio y simple.

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



Esta es la versión simple, obviamente querrá agregar alguna comprobación de errores:

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


Esta parece ser la mejor solución ya que toma en consideración múltiples parámetros del mismo nombre.

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

Luego, decidí convertirlo a un plugin de 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

Ahora, el primero solo aceptará los parámetros, pero el complemento jQuery tomará toda la url y devolverá los parámetros serializados.


Hay una biblioteca liviana llamada YouAreI.js que ha sido probada y hace que esto sea realmente fácil.

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


Las soluciones propuestas que encontré hasta ahora no cubren escenarios más complejos.

Necesitaba convertir una cadena de consulta como

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

en un objeto como:

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

DENTRO:

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

Recopilé y adapté múltiples soluciones en una que realmente funciona:

CÓDIGO:

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


No hay una solución nativa de la que tenga conocimiento. Dojo tiene un método incorporado de deserialización si usa ese marco por casualidad.

De lo contrario, puede implementarlo usted mismo de forma simple:

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

editar: decodeURIComponent agregado ()


Otra solución basada en el último estándar de 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())) : {}; }

Tenga en cuenta que esta solución está haciendo uso de

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

y _.fromPairs ( https://lodash.com/docs#fromPairs ) de lodash por simplicidad.

Debería ser fácil crear una solución más compatible ya que tiene acceso al iterador searchParams.entries () .


PRIMERO, NECESITA DEFINIR LO QUE ES UN GET 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]; } }

Que acaba de leer:

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

y usar como:

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


Sobre la base de la respuesta de Mike Causer, he realizado esta función que tiene en cuenta múltiples params con la misma clave ( foo=bar&foo=baz ) y también parámetros separados por comas ( foo=bar,baz,bin ). También le permite buscar una determinada clave de consulta.

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

Ejemplo de entrada: foo.html?foo=bar&foo=baz&foo=bez,boz,buz&bar=1,2,3

Ejemplo de salida

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


También necesitaba tratar con + en la parte de consulta de la URL ( decodeURIComponent no ), así que adapté el código de Wolfgang para convertirme en:

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

En mi caso, estoy usando jQuery para obtener parámetros de formulario listos para URL, luego este truco para construir un objeto y luego puedo actualizar fácilmente los parámetros en el objeto y reconstruir la URL de consulta, por ejemplo:

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


Tuve el mismo problema, intenté las soluciones aquí, pero ninguna de ellas funcionó realmente, ya que tenía matrices en los parámetros de URL, como esta:

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

Así que terminé escribiendo mi propia función JS, que hace una matriz del parametro en 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; }


Una solución concisa:

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


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


Uso de ES6, API de URL y API de 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; }


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