Wie konvertiere ich URL-Parameter in ein JavaScript-Objekt?

223

Ich habe eine Zeichenfolge wie diese:

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

Wie kann ich es in ein solches JavaScript-Objekt konvertieren?

{
  abc: 'foo',
  def: '[asf]',
  xyz: 5
}
Alex
quelle
1
Es ist nicht: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/… developer.mozilla.org/en-US/docs/Web/API/URL/… (obwohl wir warten müssen a etwas länger, bis alle Browser dies erkannt haben)
Arthur

Antworten:

334

Bearbeiten

Diese Bearbeitung verbessert und erklärt die Antwort anhand der Kommentare.

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

Beispiel

Analysieren Sie abc=foo&def=%5Basf%5D&xyz=5in fünf Schritten:

  • decodeURI: abc = foo & def = [asf] & xyz = 5
  • Escape-Anführungszeichen: Gleich, da keine Anführungszeichen vorhanden sind
  • Ersetzen &: abc=foo","def=[asf]","xyz=5
  • Ersetzen =: abc":"foo","def":"[asf]","xyz":"5
  • Mit Locken und Zitaten umgeben: {"abc":"foo","def":"[asf]","xyz":"5"}

Das ist legal JSON.

Eine verbesserte Lösung ermöglicht mehr Zeichen in der Suchzeichenfolge. Es verwendet eine Reviver-Funktion für die URI-Decodierung:

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

Beispiel

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

gibt

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

Ursprüngliche Antwort

Ein Einzeiler:

JSON.parse('{"' + decodeURI("abc=foo&def=%5Basf%5D&xyz=5".replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}')
Wolfgang Kühn
quelle
4
Damit dies in CoffeeScript funktioniert, maskieren Sie das '=' in der Regex. .replace (/ \ = / g, "\": \ "")
Airlok
175
Das ist kein Einzeiler ... es ist eine Raumstation.
Ziggy
5
besser, wenn Sie verwendenJSON.parse('{"' + decodeURI(location.search.substring(1).replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
Daniël Tulp
4
Dies schlägt fehl, wenn Sie in der zu analysierenden URL ein Gleichheitszeichen haben. EX: "cookie = dlksdlfj = sodkfjhsdlfj"
jholloman
3
Funktioniert auch nicht, wenn Sie einen der Parameter ohne Wert haben.
Sych
113

2020 ES6 / 7/8 und auf Annäherung

Ab ES6 bietet Javascript mehrere Konstrukte an, um eine performante Lösung für dieses Problem zu erstellen.

Dies umfasst die Verwendung von URLSearchParams und Iteratoren

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

Sollte Ihr Anwendungsfall erfordern, dass Sie es tatsächlich in ein Objekt konvertieren, können Sie die folgende Funktion implementieren:

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

Grundlegende Demo

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

Verwenden von Object.fromEntries und verbreiten

Wir verwenden Object.fromEntries (die derzeit in der Stufe 4), ersetzt paramsToObjectmit Object.fromEntries(entries).

Die zu wiederholenden Wertepaare sind die Listennamen-Wert-Paare, wobei der Schlüssel der Name und der Wert der Wert ist.

Da URLParamsein iterierbares Objekt zurückgegeben wird, führt die Verwendung des Spread-Operators anstelle des Aufrufs .entriesauch zu Einträgen gemäß seiner Spezifikation:

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

Hinweis: Alle Werte sind automatisch Zeichenfolgen gemäß der URLSearchParams-Spezifikation

Mehrere gleiche Schlüssel

Wie @siipe hervorhob , werden Zeichenfolgen, die mehrere Werte mit demselben Schlüssel enthalten, zum letzten verfügbaren Wert gezwungen: foo=first_value&foo=second_valuewird im Wesentlichen zu : {foo: "second_value"}.

Gemäß dieser Antwort: https://stackoverflow.com/a/1746566/1194694 gibt es keine Spezifikation für die Entscheidung, was damit zu tun ist, und jedes Framework kann sich anders verhalten.

Ein häufiger Anwendungsfall besteht darin, die beiden gleichen Werte zu einem Array zusammenzufügen und das Ausgabeobjekt in Folgendes umzuwandeln:

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

Dies kann mit folgendem Code erreicht werden:

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}
Silicakes
quelle
2
Ich empfehle diese Lösung nicht. URLSearchParams hat unlogische Spezifikationen ( developer.mozilla.org/en-US/docs/Web/API/… )
Seph Reed
1
Es tut mir leid, aber die Logik hat nichts damit zu tun. Man könnte argumentieren, dass es sich um einen search stringParser handelt - wofür er entwickelt wurde, unabhängig davon,
ob
Object.fromEntriesfunktioniert nicht für wiederholte Tasten. Wenn wir versuchen, so etwas zu tun ?foo=bar1&foo=bar2, bekommen wir nur { foo: 'bar2' }. Das Anforderungsobjekt von Node.js analysiert es beispielsweise als{ foo: ['bar1', 'bar2'] }
Siipe
Sie haben Recht, aber dies hat keine Spezifikation und viele Sprachen verfolgen
silicakes
Das sieht für mich gut aus, aber um die Werte für den sich wiederholenden Schlüssel zu erhalten, können wir diesen verwenden let temp={};Object.keys(params).map(key=>{temp[key]=urlParams.getAll(key)})
Tirumaleshwar Keregadde
45

ES6 Einzeiler. Sauber und einfach.

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

Für Ihren speziellen Fall wäre es:

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

Hühner
quelle
Dies fällt den Fallstricken zum Opfer. "http://place.com?foo=bar&hello=%40world&showThing"produziert{ hello: "@world", http://place.com?foo: "bar", showThing: "" }
Seph Reed
1
Sie sollten es mit einer Abfragezeichenfolge (von location.search) wie "foo = bar & hello =% 40world & showThing" verwenden, nicht mit der gesamten URL, wie die Frage nahelegt.
Hühner
1
Dies kann verwendet werden, aber mit Vorsicht ?someValue=falsewird{ someValue: "false" }
Simon
Es funktioniert nicht für wiederholte Tasten. Wenn wir versuchen, so etwas zu tun?foo=bar1&foo=bar2 , bekommen wir nur { foo: 'bar2' }. Das Anforderungsobjekt von Node.js analysiert es als{ foo: ['bar1', 'bar2'] }
Siipe
@SephReed, ich glaube, Ihr Kommentar wird mit der aktualisierten Version behandelt, die verwendetlocation.search
KyleMit
27

Teilen Sie auf &, um Name / Wert-Paare zu erhalten, und teilen Sie dann jedes Paar auf =. Hier ist ein Beispiel:

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

Ein anderer Ansatz, der reguläre Ausdrücke verwendet:

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

Dies ist aus John Resigs "Suchen und nicht ersetzen" angepasst .

Wayne
quelle
tx! Sie sollten auch decodeURIComponen (p [0]) links hinzufügen :)
Alex
Das erste Beispiel funktioniert nicht mit einer leeren Abfragezeichenfolge.
Michał Perłakowski
18

Eine prägnante Lösung:

location.search
  .slice(1)
  .split('&')
  .map(p => p.split('='))
  .reduce((obj, pair) => {
    const [key, value] = pair.map(decodeURIComponent);
    return ({ ...obj, [key]: value })
  }, {});
Clemens Helm
quelle
Dies schlägt mit Arrays fehl, dh: x = 1 & x = 2
Sh eldeeb
16

Die vorgeschlagenen Lösungen, die ich bisher gefunden habe, decken keine komplexeren Szenarien ab.

Ich musste eine Abfragezeichenfolge wie konvertieren

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 ein Objekt wie:

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

ODER:

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

Ich habe mehrere Lösungen zusammengestellt und angepasst, die tatsächlich funktionieren:

CODE:

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;
};
Mauricio van der Maesen
quelle
Dies ist die beste Antwort, da komplexe Abfragen tatsächlich ordnungsgemäß behandelt werden.
Georgy Ivanov
Ich denke, das macht die Dinge nur komplizierter, ich würde einfach bestehen obj=encodeURIComponent(JSON.stringify({what:{ever:','},i:['like']})).
Hühner
15

Dies ist die einfache Version. Natürlich möchten Sie einige Fehlerprüfungen hinzufügen:

var obj = {};
var pairs = queryString.split('&');
for(i in pairs){
    var split = pairs[i].split('=');
    obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}
Justin Niessner
quelle
1
Haben Sie nicht vergessen, die Zeichenfolge zu entschlüsseln, um% 5B und% 5D in Zeichen umzuwandeln?
jfriend00
@Alex - Haben Sie den aktualisierten Code oder das Original verwendet? Original hatte ein Problem und einen Tippfehler.
Justin Niessner
Es kann nicht richtig mit Parametern umgehen, wenn ihre Werte '=' enthalten. Es schneidet die Werte auf das erste '='.
Greck
JSON.parse('{"' + decodeURIComponent(query.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'));arbeitet für mich
Danil Gaponov
1
es funktioniert nicht für name[]=test1&name[]=test2und es wird dazu führenname[]=test2
Rafee
10

Ich fand $ .String.deparam die vollständigste vorgefertigte Lösung (kann verschachtelte Objekte usw. ausführen ). Lesen Sie die Dokumentation .

Daff
quelle
Wenn Sie nur darauf hinweisen, dass Ihre Eingabe immer eine serialisierte Abfragezeichenfolge sein wird, müssen Sie sich keine Gedanken über das Verschachteln machen, und eine leichtere Lösung ist wahrscheinlich besser
mattacular
Natürlich ... aber es wurde bereits durchgeführt und getestet (Justin hat beispielsweise vergessen, die URI in der ersten Antwort zu dekodieren - dies sind kleine Probleme, die die Dinge viel komplexer machen können, als sie zunächst scheinen).
Daff
9

2019 Einzeiler-Ansatz

Für Ihren speziellen Fall:

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

Für den allgemeineren Fall, in dem jemand Abfrageparameter für ein Objekt analysieren möchte:

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

Wenn Sie Object.fromEntries nicht verwenden können, funktioniert dies auch:

Array.from(new URLSearchParams(window.location.search)).reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
David Hansen
quelle
Also[...new URLSearchParams(window.location.search)].reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
dman
1
URLSearchParams hat einige Fallstricke, für die dies unterbrochen wird. "http://place.com?foo=bar&hello=%40world&showThingproduziert { hello: "@world", http://place.com?foo: "bar", showThing: "" }. Versuchen Sie hinzuzufügenstr.split("?").pop()
Seph Reed
7

Eine weitere Lösung, die auf dem neuesten Standard von URLSearchParams basiert ( 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()))
    : {};
}

Bitte beachten Sie, dass diese Lösung verwendet wird

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

und _.fromPairs ( https://lodash.com/docs#fromPairs ) von lodash der Einfachheit halber.

Es sollte einfach sein, eine kompatiblere Lösung zu erstellen, da Sie Zugriff auf den Iterator searchParams.entries () haben .

Nickey
quelle
6

Ich hatte das gleiche Problem, habe die Lösungen hier ausprobiert, aber keine davon hat wirklich funktioniert, da ich Arrays in den URL-Parametern hatte, wie folgt:

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

Also habe ich meine eigene JS-Funktion geschrieben, die aus dem Parameter in URI ein Array macht:

/**
 * 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;
}
pcigler
quelle
2
Das war sehr hilfreich und hat fast genau das getan, was ich wollte. Mir hat jedoch nicht gefallen, wie das "[]" im Objekt im Takt gehalten wird, wenn die URL-Parameter wie folgt lauten: bacon [] = Eier & bacon [] = Toast. Also habe ich in einer Zeile hinzugefügt , nachdem if(chunk[0].search("\\[\\]") !== -1) {das istchunk[0]=chunk[0].replace(/\[\]$/,'');
rgbflawed
@rgbflawed Sie sollten die Antwort für zukünftige Leser und Lesbarkeit
bearbeiten
Verwenden Sie conststatt, varweil jemand dies tun könnte createObjFromURI = 'some text'und dann den Code durcheinander bringen würde. Wenn Sie verwenden, constwird jemand createObjFromURI = 'some text', der einen Fehler macht, der konstanten Variablen keinen Wert zuweisen können.
Justin Liu
5

Verwenden von ES6, URL API und URLSearchParams API.

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;
}
supergentle
quelle
5

ES6 One Liner (wenn wir es so nennen können, wenn wir die lange Schlange sehen)

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

Fadomire
quelle
2
Sie können das auch curfür zusätzliche Klarheit destrukturieren . .reduce((prev, [key, val]) => {prev[key] = val})
Allan Lei
Ich mag Ihren Vorschlag Allan Lei. Ich aktualisiere meine Antwort
Fadomire
3

Ziemlich einfach mit der URLSearchParamsJavaScript-Web-API,

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

Nützliche Links

HINWEIS : Wird im IE nicht unterstützt

Erisan Olasheni
quelle
3

Für Node JS können Sie die Node JS-API verwenden querystring:

const querystring = require('querystring');

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

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

Etoxin
quelle
2

Es gibt keine native Lösung, die mir bekannt ist. Dojo verfügt über eine integrierte Unserialisierungsmethode, wenn Sie dieses Framework zufällig verwenden.

Ansonsten können Sie es ganz einfach selbst implementieren:

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

edit: decodeURIComponent () hinzugefügt

mattacular
quelle
2

Es gibt eine leichte Bibliothek namens YouAreI.js , die getestet wurde und dies wirklich einfach macht.

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' }
Stahl
quelle
2

Eine der einfachsten Möglichkeiten, dies über die URLSearchParam-Schnittstelle zu tun.

Unten ist das Arbeitscode-Snippet:

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;
   });
Rishu Ranjan
quelle
1

Dies scheint die beste Lösung zu sein, da mehrere gleichnamige Parameter berücksichtigt werden.

    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

Ich habe mich später entschlossen, es auch in ein jQuery-Plugin zu konvertieren ...

$.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

Jetzt akzeptiert der erste nur die Parameter, aber das jQuery-Plugin übernimmt die gesamte URL und gibt die serialisierten Parameter zurück.

jQuery Junkie
quelle
1

Hier ist eine, die ich benutze:

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

Grundlegende Verwendung, z.
?a=aa&b=bb
Object {a: "aa", b: "bb"}

Doppelte Parameter, z.
?a=aa&b=bb&c=cc&c=potato
Object {a: "aa", b: "bb", c: ["cc","potato"]}

Fehlende Schlüssel, z.
?a=aa&b=bb&=cc
Object {a: "aa", b: "bb"}

Fehlende Werte, z.
?a=aa&b=bb&c
Object {a: "aa", b: "bb"}

Die obigen JSON / Regex-Lösungen werfen einen Syntaxfehler auf diese verrückte URL:
?a=aa&b=bb&c=&=dd&e
Object {a: "aa", b: "bb", c: ""}

Mike Causer
quelle
1

Hier ist meine schnelle und schmutzige Version, die im Grunde genommen die durch '&' getrennten URL-Parameter in Array-Elemente aufteilt und dann über dieses Array iteriert und Schlüssel / Wert-Paare hinzufügt, die durch '=' in ein Objekt getrennt sind. Ich verwende decodeURIComponent (), um die codierten Zeichen in ihre normalen Zeichenfolgenäquivalente zu übersetzen (so wird% 20 zu einem Leerzeichen,% 26 zu '&' usw.):

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

Beispiel:

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

kehrt zurück

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

Das einzige Problem ist, dass xyz eine Zeichenfolge und keine Zahl ist (aufgrund der Verwendung von decodeURIComponent ()), aber darüber hinaus kein schlechter Ausgangspunkt.

Eric
quelle
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;
}
XYz Amos
quelle
Ich mag diese Methode (2017) im Vergleich zu einigen anderen Regex-basierten Antworten sehr. Wenn Sie die Pfeilfunktion mehrfach ausfüllen (oder als herkömmliche Funktion umschreiben), sollte dies meiner Meinung nach browserübergreifend ziemlich gut funktionieren
Scribblemacher
@Scribblemacher mit seiner BabelHilfe können Sie es gut unter anderen
Bedingungen
1

Verwenden von 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;
    }
  }
}
Duy Hoang
quelle
1

Aufbauend auf Mike Causers Antwort habe ich diese Funktion erstellt, die mehrere Parameter mit demselben Schlüssel berücksichtigt (foo=bar&foo=baz ) und auch durch Kommas getrennte Parameter ( foo=bar,baz,bin) berücksichtigt . Außerdem können Sie nach einem bestimmten Abfrageschlüssel suchen.

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

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

Beispielausgabe

{
    foo: ["bar","baz","bez","boz","buz"],
    bar: ["1","2","3"]
}
Gus
quelle
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
  }, {}))

aagamezl
quelle
0

ZUERST MÜSSEN SIE DEFINIEREN, WAS EIN GET VAR IST:

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

Als gerade gelesen:

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

und benutze wie:

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]];
}
Ag.
quelle
Bitte führen Sie Ihre Antworten zusammen. Bearbeiten Sie den anderen und löschen Sie diesen.
Bergi
0

Ich musste mich auch +im Abfrageteil der URL damit befassen ( decodeURIComponent nicht ), also habe ich Wolfgangs Code so angepasst, dass er:

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

In meinem Fall verwende ich jQuery, um URL-fähige Formularparameter abzurufen. Dann diesen Trick, um ein Objekt daraus zu erstellen. Anschließend kann ich problemlos Parameter für das Objekt aktualisieren und die Abfrage-URL neu erstellen, z.

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);
Dlauzon
quelle
0

Ich mache es so:

const uri = new URL('https://example.org/?myvar1=longValue&myvar2=value')
const result = {}
for (let p of uri.searchParams) {
  result[p[0]] = p[1]
}

quelle
0

Wenn Sie eine Rekursion benötigen, können Sie die winzige js-extension-ling- Bibliothek verwenden.

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

Dies gibt ungefähr Folgendes aus:

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

Hinweis: Es basiert auf der Funktion locutus parse_str ( https://locutus.io/php/strings/parse_str/ ).

ling
quelle