Ciąg zapytania JavaScript [zamknięty]


106

Czy istnieje biblioteka JavaScript, która tworzy słownik z ciągu zapytania, ASP.NET stylu?

Coś, czego można użyć, na przykład:

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

Czy „ciąg zapytania” nazywa się czymś spoza .NETdziedziny? Dlaczego nie jest location.searchpodzielony na kolekcję kluczy / wartości ?

EDYCJA : Napisałem własną funkcję, ale czy robi to jakakolwiek większa biblioteka JavaScript?





1
@davidtaubmann, że jeden jest starszy, byłoby odwrotnie. Zabawne, że w zasadzie zadają to samo, ale ze względu na format pytania chwała została zamieniona w społeczność, a druga zamknięta jako nie na temat.
Andre Figueiredo

Odpowiedzi:


11

37
To powinno być natywne dla jquery
gcb

@EvanMulawski Thanks. Wygląda na to, że wtyczka po prostu zniknęła. Dodałem inny link, który może pomóc.
Shadow2531

Metoda zapewniana przez CMS jest łatwiejsza i czystsza. Esp. jeśli nie używasz jeszcze jquery.
jcoffland,

1
Możesz polecić
Mikhus


230

Możesz wyodrębnić pary klucz / wartość z pliku właściwości location.search , ta właściwość ma część adresu URL następującą po znaku? symbol, w tym? symbol.

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
To nie jest wygrana. A co, jeśli wartość klucza zawiera znak „=”? Np. Dork.com/?equation=10=2. Można argumentować, że POWINNO być zakodowane w formacie URL, ale na pewno nie musi. Kiedyś popełniłem błąd, pisząc taką naiwną funkcję. Istnieje więcej niż jeden przypadek krawędzi, dla którego ta funkcja jest uwzględniana.
JamesBrownIsDead

6
@James, zapomniałem wspomnieć, że kilka miesięcy temu zmodyfikowałem funkcję, teraz poprawnie radzi sobie z twoim przykładem dork.com/?equation=10=2...
CMS

2
@CMS to nie obsługuje możliwości tablicy w ciągu zapytania, która jest reprezentowana jako taka, ?val=foo&val=bar&val=baz jak byś to zrobił?
Russ Bradberry

2
@RussBradberry Naprawdę nie możesz mieć val=foo&val=bar&val=baz; to musiało byćval[]=foo&val[]=bar&val[]=baz
Brian Driscoll,

1
Wydawało mi się to niekompletne, gdy moje wartości miały spacje, a moje zmienne kończyły się na %20s, więc zastąpiłem result[keyValuePair[0]] = keyValuePair[1] || '';jeresult[keyValuePair[0]] = decodeURIComponent((keyValuePair[1]+'').replace(/\+/g, '%20')) || '';
user24601

22

tl; dr rozwiązanie w pojedynczym (ish) wierszu kodu przy użyciu zwykłego javascript

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

W przypadku zapytania ?a=1&b=2&c=3&d&ezwraca:

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

klucze wielowartościowe i zakodowane znaki ?

Zobacz oryginalną odpowiedź w artykule Jak uzyskać wartości ciągu zapytania w języku 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
to nie jest pojedyncza linia - to kilka linii źle sformatowanych!
JonnyRaa

1
Cholera, nie wiem co powiedzieć ... Masz mnie. Oto kilka wielowierszowych rozwiązań: `var queryDict = {}; location.search.substr (1) .split ("&"). forEach (function (item) {queryDict [item.split ("=") [0]] = item.split ("=") [1]; }); `
Qwerty,

2
haha uwielbiam to! Przepraszam, że kiedyś pracowałem z kimś, kto zwykł mówić „Znalazłem jedną linijkę, która robi x”, a potem po prostu pokazałem ci 3 linie z usuniętymi przerwami!
JonnyRaa

@JonnyLeeds Nie ma problemu, dokładnie wiem, co masz na myśli, ale w takim razie, po co zapisywać każde z połączonych poleceń w nowej linii? Następnie istnieje funkcja podana jako parametr (parametry są zwykle wbudowane), która ma tylko jedno przypisanie. Krzyczy, aby być podpiętym! : D
Qwerty

1
@Qwerty, prawdopodobnie dlatego, że Twój „jednoliniowy” powinien zostać sformatowany, aby jego czytanie nie wymagało przewijania w poziomie. Dostosowałem to.
P i

8

Po znalezieniu tego posta, patrząc na siebie, pomyślałem, że powinienem dodać, że nie sądzę, aby rozwiązanie, które uzyskało najwięcej głosów, jest najlepsze. Nie obsługuje wartości tablicowych (takich jak? A = foo & a = bar - w tym przypadku spodziewałbym się zwrócenia a ['foo', 'bar']). O ile wiem, nie bierze pod uwagę zakodowanych wartości - takich jak kodowanie znaków szesnastkowych, gdzie% 20 reprezentuje spację (przykład:? A = Hello% 20World) lub symbol plus używany do reprezentowania spacji (przykład :? a = Hello + World).

Node.js oferuje coś, co wygląda na bardzo kompletne rozwiązanie do analizowania zapytań. Byłby łatwy do wyjęcia i wykorzystania we własnym projekcie, ponieważ jest on dość dobrze odizolowany i podlega liberalnej licencji.

Kod do tego można obejrzeć tutaj: https://github.com/joyent/node/blob/master/lib/querystring.js

Testy, które przeprowadził Node, można zobaczyć tutaj: https://github.com/joyent/node/blob/master/test/simple/test-querystring.js Sugerowałbym wypróbowanie niektórych z nich z popularną odpowiedzią, aby zobaczyć, jak to obsługuje je.

Jest też projekt, w którym byłem zaangażowany, aby specjalnie dodać tę funkcjonalność. Jest to port standardowego modułu analizującego łańcuchy zapytań lib w języku Python. Mój widelec można znaleźć tutaj: https://github.com/d0ugal/jquery.qeeree


Nie ma po prostu pożyczenia kodu z Node, js, jest on silnie spleciony.
alfwatt

5

Możesz też skorzystać z biblioteki sugar.js .

Z sugarjs.com:

Object.fromQueryString (str , deep = true )

Konwertuje ciąg zapytania adresu URL na obiekt. Jeśli deep jest fałszywe, konwersja będzie akceptować tylko płytkie parametry (tj. Żaden obiekt lub tablice ze składnią []), ponieważ nie są one powszechnie obsługiwane.

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

Przykład:

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

3

Jeśli masz pod ręką querystring, użyj tego:

 /**
 * @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);

To mniej więcej to samo, co kod „Aktualizacja: nie ma potrzeby używania wyrażenia regularnego” w powyższej odpowiedzi, która uzyskała najwyższą liczbę głosów . W tym pytaniu jest też mnóstwo podobnego kodu ). Brakuje ci decodeURIComponentprzynajmniej wyodrębnionych strun.
Rup

@Rup, aktualizacja została dokonana po tej odpowiedzi.
Qwerty

@Qwerty Nie, nie było: aktualizacja miała miejsce w lutym 2013 r., Podczas gdy ta odpowiedź była prawie rok później, w lutym 2014 r. Ale kogo to obchodzi, jest wiele podobnych kodów. Moje uwagi na temat decodeURIComponentstoiska.
Rup

@Rup Tak, przepraszam. I tak.
Qwerty,

2

Warto zauważyć, że biblioteka, o której wspomniał John Slegers, ma zależność od jQuery, jednak tutaj jest wersja, która jest zwykłym Javascriptem.

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

Po prostu skomentowałbym jego post, ale brakuje mi do tego reputacji. : /

Przykład:

Poniższy przykład przetwarza następujący, choć nieregularny, ciąg zapytania:

?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>


Właściwie to usunąłem zależność jQuery w kodzie, który podałem w odpowiedzi ;-)
John Slegers

2

Kod

This Gist autorstwa Eldona McGuinnessa jest zdecydowanie najbardziej kompletną implementacją parsera ciągu zapytań JavaScript, jaką widziałem do tej pory.

Niestety jest napisany jako wtyczka jQuery.

Przepisałem go na waniliowy JS i wprowadziłem kilka ulepszeń:

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

Jak tego użyć

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

Wynik

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

Zobacz także to 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]);
        }
    }
}

Możesz także .toLowerCase () nazwę, jeśli chcesz, aby dopasowywanie hfname nie uwzględniało wielkości liter.
Shadow2531

Możesz również sprawdzić, czy wartość jest pusta, czy nie. Jeśli tak, możesz pominąć dodawanie wpisu, aby tablica zawierała tylko niepuste wartości.
Shadow2531

1
unescape () nie obsługuje sekwencji UTF-8, więc możesz chcieć użyć decodeURIComponent (). Jednakże, jeśli chcesz, aby znaki + były dekodowane do spacji, uruchom .replace (/ \ + / g, "") na łańcuchu przed zdekodowaniem.
Shadow2531

1

Lubię, gdy jest to proste, czytelne i małe.

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

Przykład:

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

1

Funkcja, którą napisałem dla wymagania podobnego do tego z czystą manipulacją ciągiem 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;
}

Stosowanie:

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

Zgrabnie, ale poza sposobem, w jaki usuwasz prowadzenie ?, jest to w zasadzie to samo, co dwie odpowiedzi nad tobą?
Rup

Tylko mała poprawa. Sposób użycia tej metody ułatwia użytkownikowi. Użytkownik musi tylko wiedzieć, jakiej wartości ciągu zapytania potrzebuje.
Pranavan Maru

1

Jeśli używasz lodash + ES6, oto jedno liniowe rozwiązanie: _.object(window.location.search.replace(/(^\?)/, '').split('&').map(keyVal => keyVal.split('=')));


0

Okay, ponieważ wszyscy ignorują moje rzeczywiste pytanie, heh, moje też opublikuję! Oto co mam:

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

A testy:

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

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

Pamiętaj, że JavaScript nie jest moim językiem ojczystym.

W każdym razie szukam biblioteki JavaScript (np. JQuery, Prototype), która ma już napisaną. :)


1
Nie jestem przekonany, że naprawdę potrzebujesz biblioteki, aby zrobić trzy wiersze kodu powyżej! Mimo to, przynajmniej masz nadzieję, że biblioteka zapamięta decodeURIComponent () zarówno klucz, jak i wartość, czego nie udało się zrobić w każdym opublikowanym dotychczas fragmencie kodu.
bobince

Nie potrzebujesz biblioteki. Chciałem porównać moją implementację z tą w bibliotece, żeby zobaczyć, czy nie brakuje mi żadnych skrajnych przypadków. :)
rdzeń

javascript nie jest Twoim językiem ojczystym, co to znaczy, powinieneś się go nauczyć, nawet jeśli potrzebujesz biblioteki
Marwan

0

Opierając się na odpowiedzi @CMS, mam następujące elementy (w CoffeeScript, który można łatwo przekonwertować na 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

Możesz łatwo pobrać to, czego potrzebujesz, dzięki:

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

Tutaj wygrywa interfejs zorientowany obiektowo (zamiast funkcjonalnego) i można to zrobić na dowolnym ciągu znaków (nie tylko na location.search).

Jeśli korzystasz już z biblioteki JavaScript, ta funkcja już istnieje. Na przykład tutaj jest wersja Prototype

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.