Comment convertir des paramètres d'URL en un objet JavaScript?

223

J'ai une chaîne comme celle-ci:

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

Comment puis-je le convertir en un objet JavaScript comme celui-ci?

{
  abc: 'foo',
  def: '[asf]',
  xyz: 5
}
Alex
la source
1
Ce n'est pas: developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/… developer.mozilla.org/en-US/docs/Web/API/URL/… (bien que nous devrons attendre un peu de temps pour que tous les navigateurs aient compris)
Arthur

Réponses:

335

Éditer

Cette modification améliore et explique la réponse sur la base des commentaires.

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

Exemple

Analysez abc=foo&def=%5Basf%5D&xyz=5en cinq étapes:

  • decodeURI: abc = foo & def = [asf] & xyz = 5
  • Citations d'échappement: mêmes, car il n'y a pas de citations
  • Remplacer &: abc=foo","def=[asf]","xyz=5
  • Remplacer =: abc":"foo","def":"[asf]","xyz":"5
  • Entourez de curlies et de citations: {"abc":"foo","def":"[asf]","xyz":"5"}

qui est JSON légal.

Une solution améliorée permet d'ajouter plus de caractères dans la chaîne de recherche. Il utilise une fonction reviver pour le décodage URI:

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

Exemple

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

donne

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

Réponse originale

Un one-liner:

JSON.parse('{"' + decodeURI("abc=foo&def=%5Basf%5D&xyz=5".replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}')
Wolfgang Kuehn
la source
4
Pour que cela fonctionne dans CoffeeScript, échappez au '=' dans l'expression régulière. .replace (/ \ = / g, "\": \ "")
airlok
175
Ce n'est pas un paquebot ... c'est une station spatiale.
Ziggy
5
mieux si vous utilisezJSON.parse('{"' + decodeURI(location.search.substring(1).replace(/&/g, "\",\"").replace(/=/g, "\":\"")) + '"}')
Daniël Tulp
4
Cela échoue si vous avez un caractère de signe égal dans l'URL à analyser. EX: "cookie = dlksdlfj = sodkfjhsdlfj"
jholloman
3
Ne fonctionne pas non plus lorsque vous avez l'un des paramètres sans valeur.
Sych
113

2020 ES6 / 7/8 et en approche

À partir d'ES6 et suivants, Javascript propose plusieurs constructions afin de créer une solution performante pour ce problème.

Cela inclut l'utilisation de URLSearchParams et des itérateurs

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

Si votre cas d'utilisation vous oblige à le convertir réellement en objet, vous pouvez implémenter la fonction suivante:

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

Démo de base

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

Utilisation d'Object.fromEntries et propagation

Nous pouvons utiliser Object.fromEntries (qui est actuellement à l'étape 4), en remplaçant paramsToObjectpar Object.fromEntries(entries).

Les paires de valeurs sur lesquelles itérer sont les paires nom-valeur de liste, la clé étant le nom et la valeur étant la valeur.

Depuis URLParams, retourne un objet itérable , utiliser l' opérateur spread au lieu d'appeler .entriesproduira également des entrées selon sa spécification:

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

Remarque: Toutes les valeurs sont automatiquement des chaînes selon la spécification URLSearchParams

Plusieurs clés identiques

Comme @siipe a souligné, des chaînes contenant plusieurs valeurs de même clés seront contraints à la dernière valeur disponible: foo=first_value&foo=second_valuesera essentiellement devenir: {foo: "second_value"}.

Selon cette réponse: https://stackoverflow.com/a/1746566/1194694 il n'y a aucune spécification pour décider quoi en faire et chaque framework peut se comporter différemment.

Un cas d'utilisation courant consistera à joindre les deux mêmes valeurs dans un tableau, transformant l'objet de sortie en:

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

Cela peut être réalisé avec le code suivant:

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
la source
2
Je ne recommande pas cette solution. URLSearchParams a des spécifications illogiques ( developer.mozilla.org/en-US/docs/Web/API/… )
Seph Reed
1
Je suis désolé mais la logique n'a rien à voir avec ça. On pourrait dire que c'est un search stringanalyseur - c'est ce qu'il a été conçu pour faire, indépendamment du fait qu'il soit associé à une URL
silicakes
Object.fromEntriesne fonctionne pas pour les touches répétées. Si nous essayons de faire quelque chose comme ça ?foo=bar1&foo=bar2, nous n'obtiendrons que { foo: 'bar2' }. L'objet de requête Node.js, par exemple, le traite comme{ foo: ['bar1', 'bar2'] }
Siipe
Vous avez raison, mais cela n'a aucune spécification et de nombreuses langues adoptent une approche avisée quant à la façon de l'analyser: stackoverflow.com/a/1746566/1194694
silicakes
Cela me semble bien, mais pour obtenir les valeurs de la clé répétitive, nous pouvons l'utiliser let temp={};Object.keys(params).map(key=>{temp[key]=urlParams.getAll(key)})
Tirumaleshwar Keregadde
45

ES6 une doublure. Propre et simple.

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

Pour votre cas spécifique, ce serait:

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

poulets
la source
Cela tombe en proie aux pièges. "http://place.com?foo=bar&hello=%40world&showThing"produit{ hello: "@world", http://place.com?foo: "bar", showThing: "" }
Seph Reed
1
Vous devez l'utiliser avec une chaîne de requête (de location.search) comme "foo = bar & hello =% 40world & showThing" et non l'url entière, comme le suggère la question.
poulets
1
Cela peut être utilisé, mais avec prudence ?someValue=falsedevient{ someValue: "false" }
Simon
Cela ne fonctionne pas pour les touches répétées. Si nous essayons de faire quelque chose comme ?foo=bar1&foo=bar2, nous n'obtiendrons que { foo: 'bar2' }. L'objet de requête Node.js le traite comme{ foo: ['bar1', 'bar2'] }
Siipe
@SephReed, je crois que votre commentaire est traité avec la version mise à jour qui utiliselocation.search
KyleMit
27

Partager & pour obtenir des paires nom / valeur, puis divisez chaque paire =. Voici un exemple:

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

Une autre approche, utilisant des expressions régulières:

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

Ceci est adapté de John Resig "Search and Don't Replace" .

Wayne
la source
tx! vous devez également ajouter decodeURIComponen (p [0]) à gauche :)
Alex
Le premier exemple ne fonctionne pas avec une chaîne de requête vide.
Michał Perłakowski
18

Une solution concise:

location.search
  .slice(1)
  .split('&')
  .map(p => p.split('='))
  .reduce((obj, pair) => {
    const [key, value] = pair.map(decodeURIComponent);
    return ({ ...obj, [key]: value })
  }, {});
Heaume Clemens
la source
cela échoue avec les tableaux ie: x = 1 & x = 2
Sh eldeeb
16

Les solutions proposées jusqu'à présent ne couvrent pas des scénarios plus complexes.

J'avais besoin de convertir une chaîne de requête comme

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

dans un objet comme:

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

OU:

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

DANS:

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

J'ai compilé et adapté plusieurs solutions en une seule qui fonctionne réellement:

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
la source
C'est la meilleure réponse, car elle gère en effet correctement les requêtes complexes.
Georgy Ivanov
Je pense que cela complique les choses, je passerais obj=encodeURIComponent(JSON.stringify({what:{ever:','},i:['like']})).
poulets
15

Ceci est la version simple, vous voudrez évidemment ajouter une vérification des erreurs:

var obj = {};
var pairs = queryString.split('&');
for(i in pairs){
    var split = pairs[i].split('=');
    obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}
Justin Niessner
la source
1
N'avez-vous pas oublié de décoder la chaîne pour convertir les% 5B et% 5D en caractères?
jfriend00
@Alex - Avez-vous utilisé le code mis à jour ou l'original? Original avait un problème et une faute de frappe.
Justin Niessner
Il ne peut pas gérer correctement les paramètres lorsque leurs valeurs contiennent «=». Il ajuste les valeurs au premier «=».
Greck
JSON.parse('{"' + decodeURIComponent(query.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}'));travaille pour moi
Danil Gaponov
1
son ne fonctionne pas name[]=test1&name[]=test2et il en résulteraname[]=test2
Rafee
10

J'ai trouvé $ .String.deparam la solution pré-construite la plus complète (peut faire des objets imbriqués, etc.). Consultez la documentation .

Daff
la source
il suffit de souligner que si votre entrée sera toujours une chaîne de requête sérialisée, il n'y a pas besoin de s'inquiéter de l'imbrication et une solution plus légère est probablement meilleure
mattacular
Bien sûr ... mais cela a déjà été fait et testé (Justin oublie par exemple de décoder l'URI dans la réponse initiale - qui sont de petits problèmes qui peuvent rendre les choses beaucoup plus complexes qu'elles ne le paraissent initialement).
Daff
9

Approche monoplace 2019

Pour votre cas spécifique:

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

Pour le cas plus générique où quelqu'un veut analyser les paramètres de requête vers un objet:

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

Si vous ne parvenez pas à utiliser Object.fromEntries, cela fonctionnera également:

Array.from(new URLSearchParams(window.location.search)).reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
David Hansen
la source
Aussi[...new URLSearchParams(window.location.search)].reduce((o, i) => ({ ...o, [i[0]]: i[1] }), {});
dman
1
URLSearchParams a quelques pièges pour lesquels cela se casse. "http://place.com?foo=bar&hello=%40world&showThingproduit { hello: "@world", http://place.com?foo: "bar", showThing: "" }. Essayez d'ajouterstr.split("?").pop()
Seph Reed
7

Une autre solution basée sur la dernière norme d'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()))
    : {};
}

Veuillez noter que cette solution utilise

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

et _.fromPairs ( https://lodash.com/docs#fromPairs ) de lodash par souci de simplicité.

Il devrait être facile de créer une solution plus compatible puisque vous avez accès à l' itérateur searchParams.entries () .

Nickey
la source
6

J'ai eu le même problème, j'ai essayé les solutions ici, mais aucune d'entre elles n'a vraiment fonctionné, car j'avais des tableaux dans les paramètres d'URL, comme ceci:

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

J'ai donc fini par écrire ma propre fonction JS, qui crée un tableau à partir du paramètre dans l'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;
}
pcigler
la source
2
C'était vraiment utile et a fait presque exactement ce que je voulais. Je n'ai pas aimé, cependant, comment le "[]" est maintenu intact dans l'objet si les paramètres d'URL sont comme: bacon [] = oeufs et bacon [] = toast. J'ai donc ajouté une ligne après if(chunk[0].search("\\[\\]") !== -1) {celachunk[0]=chunk[0].replace(/\[\]$/,'');
rgbflawed
@rgbflawed vous devez éditer la réponse pour le futur lecteur et la lisibilité
Webwoman
Utilisez constplutôt que varparce que quelqu'un pourrait le faire createObjFromURI = 'some text'et ensuite il gâcherait le code. si vous utilisez constalors quelqu'un qui exécute createObjFromURI = 'some text'fera une erreur ne peut pas assigner de valeur à la variable constante.
Justin Liu
5

Utilisation d'ES6, de l'API URL et de l'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;
}
supergentle
la source
5

ES6 one liner (si on peut l'appeler ainsi en voyant la longue file)

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

fadomire
la source
2
Vous pouvez également détruire le curpour plus de clarté. .reduce((prev, [key, val]) => {prev[key] = val})
Allan Lei
j'aime votre suggestion Allan Lei. Je mets à jour ma réponse
fadomire
3

Assez facile à utiliser l' URLSearchParamsAPI Web JavaScript,

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

Liens utiles

REMARQUE : non pris en charge dans IE

Erisan Olasheni
la source
3

Pour Node JS, vous pouvez utiliser l'API Node JS querystring:

const querystring = require('querystring');

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

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

étoxine
la source
2

Il n'y a pas de solution native à ma connaissance. Dojo a une méthode de désérialisation intégrée si vous utilisez ce framework par hasard.

Sinon, vous pouvez l'implémenter vous-même assez simplement:

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: ajouté decodeURIComponent ()

mataculaire
la source
2

Il y a une bibliothèque légère appelée YouAreI.js qui est testée et rend cela vraiment facile.

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' }
acier
la source
2

L'un des moyens les plus simples de le faire à l'aide de l'interface URLSearchParam.

Voici l'extrait de code de travail:

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
la source
1

Cela semble être la meilleure solution car elle prend en compte plusieurs paramètres du même nom.

    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

J'ai ensuite décidé de le convertir en plugin jQuery aussi ...

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

Maintenant, le premier n'acceptera que les paramètres mais le plugin jQuery prendra toute l'URL et retournera les paramètres sérialisés.

jQuery Junkie
la source
1

En voici un que j'utilise:

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

Utilisation de base, par exemple.
?a=aa&b=bb
Object {a: "aa", b: "bb"}

Paramètres en double, par exemple.
?a=aa&b=bb&c=cc&c=potato
Object {a: "aa", b: "bb", c: ["cc","potato"]}

Clés manquantes, par exemple.
?a=aa&b=bb&=cc
Object {a: "aa", b: "bb"}

Valeurs manquantes, par exemple.
?a=aa&b=bb&c
Object {a: "aa", b: "bb"}

Les solutions JSON / regex ci-dessus jettent une erreur de syntaxe sur cette URL farfelue:
?a=aa&b=bb&c=&=dd&e
Object {a: "aa", b: "bb", c: ""}

Mike Causer
la source
1

Voici ma version rapide et sale, essentiellement sa division des paramètres URL séparés par «&» en éléments de tableau, puis itère sur ce tableau en ajoutant des paires clé / valeur séparées par «=» dans un objet. J'utilise decodeURIComponent () pour traduire les caractères encodés en leurs équivalents de chaîne normaux (donc% 20 devient un espace,% 26 devient '&', 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;
}

exemple:

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

Retour

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

Le seul problème est que xyz est une chaîne et non un nombre (en raison de l'utilisation de decodeURIComponent ()), mais au-delà, ce n'est pas un mauvais point de départ.

Eric
la source
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
la source
J'aime vraiment cette méthode (en 2017) par rapport à certaines des autres réponses basées sur les expressions rationnelles. Si polyfill la fonction flèche (ou réécrire comme une fonction traditionnelle), je pense que cela devrait fonctionner assez bien multi-navigateur
Scribblemacher
@Scribblemacher avec Babell'aide de vous pouvez bien le faire dans un autre environnement
XYz Amos
1

Utiliser 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
la source
1

Sur la base de la réponse de Mike Causer, j'ai créé cette fonction qui prend en compte plusieurs paramètres avec la même clé ( foo=bar&foo=baz) et également des paramètres séparés par des virgules ( foo=bar,baz,bin). Il vous permet également de rechercher une certaine clé de requête.

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

Exemple d'entrée: foo.html?foo=bar&foo=baz&foo=bez,boz,buz&bar=1,2,3

Exemple de sortie

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

D'ABORD, VOUS DEVEZ DÉFINIR CE QUI EST UN VAR 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 simplement lire:

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

et utiliser comme:

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.
la source
Veuillez fusionner vos réponses. Modifiez l'autre , puis supprimez celui-ci.
Bergi
0

Je devais également traiter +dans la partie requête de l'URL ( decodeURIComponent ne le fait pas ), j'ai donc adapté le code de Wolfgang pour devenir:

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

Dans mon cas, j'utilise jQuery pour obtenir des paramètres de formulaire prêts pour l'URL, puis cette astuce pour en construire un objet et je peux ensuite facilement mettre à jour les paramètres de l'objet et reconstruire l'URL de la requête, par exemple:

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
la source
0

Je le fais de cette façon:

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

la source
0

Si vous avez besoin d'une récursivité, vous pouvez utiliser la minuscule bibliothèque js-extension-ling .

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

Cela produira quelque chose comme ceci:

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

Remarque: il est basé sur la fonction locutus parse_str ( https://locutus.io/php/strings/parse_str/ ).

lingue
la source