Cadena de consulta de JavaScript [cerrada]


106

¿Existe alguna biblioteca de JavaScript que haga un diccionario a partir de la cadena de consulta, ASP.NETestilo?

Algo que se puede utilizar como:

var query = window.location.querystring["query"]?

¿Se llama "cadena de consulta" de otra forma fuera del .NETámbito? ¿Por qué no se location.searchdivide en una colección de clave / valor ?

EDITAR : He escrito mi propia función, pero ¿alguna biblioteca importante de JavaScript hace esto?





1
@davidtaubmann que uno es mayor, sería inverso. Es curioso que esencialmente pregunten lo mismo, pero debido al formato de la pregunta, uno consiguió que la gloria se convirtiera en la de la comunidad y la otra se cerrara como fuera de tema.
Andre Figueiredo

Respuestas:


11

37
Esto debería ser nativo de jquery
gcb

@EvanMulawski Gracias. Parece que el complemento simplemente desapareció. Agregué un enlace diferente, que podría ayudar.
Shadow2531

El método proporcionado por CMS es más fácil y limpio. Esp. si aún no está usando jquery.
jcoffland

1
Puede consultar esta biblioteca para hacer eso: github.com/Mikhus/jsurl
Mikhus

1
Aquí está el enlace adecuado: plugins.jquery.com/query-object
thexfactor

230

Puede extraer los pares clave / valor de la propiedad location.search , esta propiedad tiene la parte de la URL que sigue a? símbolo, incluido el? símbolo.

function getQueryString() {
  var result = {}, queryString = location.search.slice(1),
      re = /([^&=]+)=([^&]*)/g, m;

  while (m = re.exec(queryString)) {
    result[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }

  return result;
}

// ...
var myParam = getQueryString()["myParam"];

11
Esto no es una victoria. ¿Qué pasa si el valor de una clave tiene el carácter '='? Por ejemplo, dork.com/?equation=10=2. Se podría argumentar que DEBERÍA estar codificado en URL, pero seguro que no tiene por qué serlo. Cometí el error de escribir una función ingenua como esta una vez. Hay más de un caso de borde que esta función tiene en cuenta.
JamesBrownIsDead

6
@James, olvidé mencionar que hace un par de meses modifiqué la función, ahora puede manejar correctamente su ejemplo dork.com/?equation=10=2...
CMS

2
@CMS esto no maneja la posibilidad de una matriz en una cadena de consulta que se representa como tal, ?val=foo&val=bar&val=baz ¿cómo se adaptaría a esto?
Russ Bradberry

2
@RussBradberry Realmente no puedes tener val=foo&val=bar&val=baz; tendría que serval[]=foo&val[]=bar&val[]=baz
Brian Driscoll

1
Me pareció incompleto cuando mis valores tenían espacios y mis vars terminaron con %20's, así que lo reemplacé result[keyValuePair[0]] = keyValuePair[1] || '';conresult[keyValuePair[0]] = decodeURIComponent((keyValuePair[1]+'').replace(/\+/g, '%20')) || '';
user24601

22

tl; dr solución en una sola línea (ish) de código usando vainilla javascript

var queryDict = {}
location.search.substr(1).split("&").forEach(function(item) {
    queryDict[item.split("=")[0]] = item.split("=")[1]
})

Para la cadena de consulta ?a=1&b=2&c=3&d&e, devuelve:

> queryDict
a: "1"
b: "2"
c: "3"
d: undefined
e: undefined

claves de varios valores y caracteres codificados ?

Vea la respuesta original en ¿Cómo puedo obtener valores de cadena de consulta en JavaScript?

"?a=1&b=2&c=3&d&e&a=5&a=t%20e%20x%20t&e=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dståle%26car%3Dsaab"
> queryDict
a: ["1", "5", "t e x t"]
b: ["2"]
c: ["3"]
d: [undefined]
e: [undefined, "http://w3schools.com/my test.asp?name=ståle&car=saab"]

8
eso no es una sola línea - ¡son varias líneas mal formateadas!
JonnyRaa

1
Maldita sea, no sé qué decir ... Me tienes. Aquí, tenga alguna solución multilínea: `var queryDict = {}; location.search.substr (1) .split ("&"). forEach (function (item) {queryDict [item.split ("=") [0]] = item.split ("=") [1]; }); `
Qwerty

2
jaja me encanta! Lo siento, solía trabajar con alguien que solía decir "Encontré un trazador de líneas que hace x" y luego solo te muestra 3 líneas con los saltos de línea eliminados.
JonnyRaa

@JonnyLeeds No hay problema, sé exactamente a qué te refieres, pero entonces, ¿por qué escribiría uno cada uno de los comandos encadenados en una nueva línea? Luego hay una función dada como parámetro (los parámetros generalmente están en línea) que tiene una sola asignación. ¡Grita para estar en línea! : D
Qwerty

1
@Qwerty, es probable que se deba a que su "una línea" debería reformatearse para que su lectura no requiera un desplazamiento horizontal. Lo he ajustado.
P i

8

Después de encontrar esta publicación, al mirarme a mí mismo pensé que debería agregar que no creo que la solución más votada sea la mejor. No maneja valores de matriz (como? A = foo & a = bar; en este caso, esperaría obtener un retorno ['foo', 'bar']). También, por lo que puedo decir, no tiene en cuenta los valores codificados, como la codificación de caracteres hexadecimales donde% 20 representa un espacio (ejemplo:? A = Hola% 20World) o el símbolo más que se usa para representar un espacio (ejemplo :? a = Hola + Mundo).

Node.js ofrece lo que parece una solución muy completa para el análisis de cadenas de consulta. Sería fácil de sacar y usar en su propio proyecto ya que está bastante bien aislado y bajo una licencia permisiva.

El código se puede ver aquí: https://github.com/joyent/node/blob/master/lib/querystring.js

Las pruebas que tiene Node se pueden ver aquí: https://github.com/joyent/node/blob/master/test/simple/test-querystring.js Sugeriría probar algunas de estas con la respuesta popular para ver cómo funciona los maneja.

También hay un proyecto en el que participé para agregar específicamente esta funcionalidad. Es un puerto del módulo de análisis de cadenas de consulta lib estándar de Python. Mi bifurcación se puede encontrar aquí: https://github.com/d0ugal/jquery.qeeree


No es solo tomar prestado el código de Node, js, está altamente entrelazado.
Alfwatt

5

O puede usar la biblioteca sugar.js .

De sugarjs.com:

Object.fromQueryString (str , deep = true )

Convierte la cadena de consulta de una URL en un objeto. Si deep es falso, la conversión solo aceptará parámetros poco profundos (es decir, ningún objeto o matrices con sintaxis []) ya que estos no son compatibles universalmente.

Object.fromQueryString('foo=bar&broken=wear') >{"foo":"bar","broken":"wear"}
Object.fromQueryString('foo[]=1&foo[]=2') >{"foo":[1,2]}

Ejemplo:

var queryString = Object.fromQueryString(location.search);
var foo = queryString.foo;

3

Si tiene la cadena de consulta a mano, use esto:

 /**
 * @param qry the querystring
 * @param name name of parameter
 * @returns the parameter specified by name
 * @author eduardo.medeirospereira@gmail.com
 */

function getQueryStringParameter(qry,name){
    if(typeof qry !== undefined && qry !== ""){
        var keyValueArray = qry.split("&");
        for ( var i = 0; i < keyValueArray.length; i++) {
            if(keyValueArray[i].indexOf(name)>-1){
                return keyValueArray[i].split("=")[1];
            }
        }
    }
    return "";
}

2
// How about this
function queryString(qs) {
    var queryStr = qs.substr(1).split("&"),obj={};
    for(var i=0; i < queryStr.length;i++)
        obj[queryStr[i].split("=")[0]] = queryStr[i].split("=")[1];
    return obj;
}

// Usage:
var result = queryString(location.search);

Eso es más o menos lo mismo que la "Actualización: no es necesario usar el código regex" en la respuesta más votada anterior. También hay un montón de código similar en esta pregunta ). Te faltan decodeURIComponental menos las cadenas extraídas.
Rup

@Rup, la actualización se realizó después de esta respuesta.
Qwerty

@Qwerty No, no lo fue: la actualización fue en febrero de 2013, mientras que esta respuesta fue casi un año después, en febrero de 2014. Pero a quién le importa, hay muchos códigos similares circulando. Sin decodeURIComponentembargo, mis comentarios sobre el stand.
Rup

@Rup Sí, lo siento. Y sí.
Qwerty

2

Vale la pena señalar que la biblioteca que mencionó John Slegers tiene una dependencia de jQuery, sin embargo, aquí hay una versión que es Javascript vanilla.

https://github.com/EldonMcGuinness/querystring.js

Simplemente habría comentado su publicación, pero no tengo la reputación para hacerlo. : /

Ejemplo:

El siguiente ejemplo procesa la siguiente cadena de consulta, aunque irregular:

?foo=bar&foo=boo&roo=bar;bee=bop;=ghost;=ghost2;&;checkbox%5B%5D=b1;checkbox%5B%5D=b2;dd=;http=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab&http=http%3A%2F%2Fw3schools2.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab 

var qs = "?foo=bar&foo=boo&roo=bar;bee=bop;=ghost;=ghost2;&;checkbox%5B%5D=b1;checkbox%5B%5D=b2;dd=;http=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab&http=http%3A%2F%2Fw3schools2.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab";
//var qs = "?=&=";
//var qs = ""

var results = querystring(qs);

(document.getElementById("results")).innerHTML =JSON.stringify(results, null, 2);
<script 
src="https://rawgit.com/EldonMcGuinness/querystring.js/master/dist/querystring.min.js"></script>
<pre id="results">RESULTS: Waiting...</pre>


En realidad, eliminé la dependencia de jQuery en el código que di en mi respuesta ;-)
John Slegers

2

El código

Esta esencia de Eldon McGuinness es, con mucho, la implementación más completa de un analizador de cadenas de consulta de JavaScript que he visto hasta ahora.

Desafortunadamente, está escrito como un complemento de jQuery.

Lo reescribí en Vanilla JS e hice algunas mejoras:

function parseQuery(str) {
  var qso = {};
  var qs = (str || document.location.search);
  // Check for an empty querystring
  if (qs == "") {
    return qso;
  }
  // Normalize the querystring
  qs = qs.replace(/(^\?)/, '').replace(/;/g, '&');
  while (qs.indexOf("&&") != -1) {
    qs = qs.replace(/&&/g, '&');
  }
  qs = qs.replace(/([\&]+$)/, '');
  // Break the querystring into parts
  qs = qs.split("&");
  // Build the querystring object
  for (var i = 0; i < qs.length; i++) {
    var qi = qs[i].split("=");
    qi = qi.map(function(n) {
      return decodeURIComponent(n)
    });
    if (typeof qi[1] === "undefined") {
      qi[1] = null;
    }
    if (typeof qso[qi[0]] !== "undefined") {

      // If a key already exists then make this an object
      if (typeof (qso[qi[0]]) == "string") {
        var temp = qso[qi[0]];
        if (qi[1] == "") {
          qi[1] = null;
        }
        qso[qi[0]] = [];
        qso[qi[0]].push(temp);
        qso[qi[0]].push(qi[1]);

      } else if (typeof (qso[qi[0]]) == "object") {
        if (qi[1] == "") {
          qi[1] = null;
        }
        qso[qi[0]].push(qi[1]);
      }
    } else {
      // If no key exists just set it as a string
      if (qi[1] == "") {
        qi[1] = null;
      }
      qso[qi[0]] = qi[1];
    }
  }
  return qso;
}

Cómo usarlo

var results = parseQuery("?foo=bar&foo=boo&roo=bar;bee=bop;=ghost;=ghost2;&;checkbox%5B%5D=b1;checkbox%5B%5D=b2;dd=;http=http%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab&http=http%3A%2F%2Fw3schools2.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab");

Salida

{
  "foo": ["bar", "boo" ],
  "roo": "bar",
  "bee": "bop",
  "": ["ghost", "ghost2"],
  "checkbox[]": ["b1", "b2"],
  "dd": null,
  "http": [
    "http://w3schools.com/my test.asp?name=ståle&car=saab",
    "http://w3schools2.com/my test.asp?name=ståle&car=saab"
  ]
}

Vea también este Fiddle .


1

function decode(s) {
    try {
        return decodeURIComponent(s).replace(/\r\n|\r|\n/g, "\r\n");
    } catch (e) {
        return "";
    }
}
function getQueryString(win) {
    var qs = win.location.search;
    var multimap = {};
    if (qs.length > 1) {
        qs = qs.substr(1);
        qs.replace(/([^=&]+)=([^&]*)/g, function(match, hfname, hfvalue) {
            var name = decode(hfname);
            var value = decode(hfvalue);
            if (name.length > 0) {
                if (!multimap.hasOwnProperty(name)) {
                    multimap[name] = [];
                }
                multimap[name].push(value);
            }
        });
    }
    return multimap;
}
var keys = getQueryString(window);
for (var i in keys) {
    if (keys.hasOwnProperty(i)) {
        for (var z = 0; z < keys[i].length; ++z) {
            alert(i + ":" + keys[i][z]);
        }
    }
}

También puede .toLowerCase () el nombre si desea que la coincidencia de hfname no distinga entre mayúsculas y minúsculas.
Shadow2531

También puede verificar si el valor está vacío o no. Si es así, puede omitir la adición de la entrada para que la matriz solo contenga valores no vacíos.
Shadow2531

1
unescape () no maneja secuencias UTF-8, por lo que es posible que desee utilizar decodeURIComponent (). Sin embargo, entonces, si desea decodificar + caracteres en espacios, ejecute .replace (/ \ + / g, "") en la cadena antes de decodificar.
Shadow2531

1

Me gusta mantenerlo simple, legible y pequeño.

function searchToObject(search) {
    var pairs = search.substring(1).split("&"),
        obj = {}, pair;

    for (var i in pairs) {
        if (pairs[i] === "") continue;
        pair = pairs[i].split("=");
        obj[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
    }
    return obj;
}

searchToObject(location.search);

Ejemplo:

searchToObject('?query=myvalue')['query']; // spits out: 'myvalue'

1

Función que escribí para un requisito similar a este con manipulación pura de cadenas de JavaScript

"http://www.google.lk/?Name=John&Age=20&Gender=Male"

function queryize(sampleurl){
    var tokens = url.split('?')[1].split('&');
    var result = {};

    for(var i=0; i<tokens.length; i++){
        result[tokens[i].split('=')[0]] = tokens[i].split('=')[1];
    }

    return result;
}

Uso:

queryize(window.location.href)['Name'] //returns John
queryize(window.location.href)['Age'] //returns 20
queryize(window.location.href)['Gender'] //returns Male

Limpio, pero aparte de la forma en que elimina el interlineado, ?es básicamente lo mismo que las dos respuestas anteriores.
Rup

Solo una pequeña mejora. La forma en que se utiliza el método lo hace fácil para el usuario. El usuario solo necesita saber qué valor de cadena de consulta necesita.
Pranavan Maru

1

Si está utilizando lodash + ES6, aquí hay una solución de una línea: _.object(window.location.search.replace(/(^\?)/, '').split('&').map(keyVal => keyVal.split('=')));


0

De acuerdo, ya que todos están ignorando mi pregunta real, je, ¡también publicaré la mía! Esto es lo que tengo:

location.querystring = (function() {

    // The return is a collection of key/value pairs

    var queryStringDictionary = {};

    // Gets the query string, starts with '?'

    var querystring = unescape(location.search);

    // document.location.search is empty if no query string

    if (!querystring) {
        return {};
    }

    // Remove the '?' via substring(1)

    querystring = querystring.substring(1);

    // '&' seperates key/value pairs

    var pairs = querystring.split("&");

    // Load the key/values of the return collection

    for (var i = 0; i < pairs.length; i++) {
        var keyValuePair = pairs[i].split("=");
        queryStringDictionary[keyValuePair[0]] = keyValuePair[1];
    }

    // Return the key/value pairs concatenated

    queryStringDictionary.toString = function() {

        if (queryStringDictionary.length == 0) {
            return "";
        }

        var toString = "?";

        for (var key in queryStringDictionary) {
            toString += key + "=" + queryStringDictionary[key];
        }

        return toString;
    };

    // Return the key/value dictionary

    return queryStringDictionary;
})();

Y las pruebas:

alert(window.location.querystring.toString());

for (var key in location.querystring) {
    alert(key + "=" + location.querystring[key]);
}

Eso sí, pensaste, JavaScript no es mi lengua materna.

De todos modos, estoy buscando una biblioteca de JavaScript (por ejemplo, jQuery, Prototype) que ya tenga una escrita. :)


1
¡No estoy convencido de que realmente necesite una biblioteca para hacer lo que equivale a tres líneas de código arriba! Aún así, al menos esperaría que una biblioteca recuerde el decodeURIComponent () tanto la clave como el valor, algo que todos los fragmentos de código publicados hasta ahora no han podido hacer.
Bobince

No necesitas una biblioteca. Quería comparar mi implementación con una en una biblioteca para poder ver si me faltaban casos extremos. :)
core

javascript no es su lengua materna, ¿qué significa? Debe aprenderlo incluso si necesita una biblioteca para usar
Marwan

0

Sobre la base de la respuesta de @CMS, tengo lo siguiente (en CoffeeScript que se puede convertir fácilmente a JavaScript):

String::to_query = ->
  [result, re, d] = [{}, /([^&=]+)=([^&]*)/g, decodeURIComponent]
  while match = re.exec(if @.match /^\?/ then @.substring(1) else @)
    result[d(match[1])] = d match[2] 
  result

Puede obtener fácilmente lo que necesita con:

location.search.to_query()['my_param']

La ganancia aquí es una interfaz orientada a objetos (en lugar de funcional) y se puede hacer en cualquier cadena (no solo en location.search).

Si ya está utilizando una biblioteca de JavaScript, esta función ya existe. Por ejemplo, aquí está la versión de Prototype

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.