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
}
Cette modification améliore et explique la réponse en fonction des commentaires.
var search = location.search.substring(1);
JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')
Exemple
Analyser abc=foo&def=%5Basf%5D&xyz=5
en cinq étapes:
abc=foo","def=[asf]","xyz=5
abc":"foo","def":"[asf]","xyz":"5
{"abc":"foo","def":"[asf]","xyz":"5"}
qui est légal JSON.
Une solution améliorée autorise 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"}
Un one-liner:
JSON.parse('{"' + decodeURI("abc=foo&def=%5Basf%5D&xyz=5".replace(/&/g, "\",\"").replace(/=/g,"\":\"")) + '"}')
Fractionner sur &
pour obtenir des paires nom/valeur, puis diviser chaque paire sur =
. 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 "Rechercher et ne pas remplacer" de John Resig .
À partir de ES6, Javascript propose plusieurs constructions pour créer une solution performante à ce problème.
Cela inclut l’utilisation de URLSearchParams et itérateurs
let params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
params.get("abc"); // "foo"
Si votre cas d'utilisation nécessite que vous le convertissiez 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
result[entry[0]] = entry[1];
}
return result;
}
let params = new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5');
let entries = params.entries(); //returns an iterator of decoded [key,value] tuples
paramsToObject(entries); //{abc:"foo",def:"[asf]",xyz:"5"}
Remarque: Toutes les valeurs sont automatiquement des chaînes selon la spécification URLSearchParams
Ceci est la version simple, vous voudrez évidemment ajouter une vérification d'erreur:
var obj = {};
var pairs = queryString.split('&');
for(i in pairs){
var split = pairs[i].split('=');
obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}
J'ai trouvé $ .String.deparam la solution prédéfinie la plus complète (peut créer des objets imbriqués, etc.). Découvrez la documentation .
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 })
}, {});
Une autre solution basée sur le dernier standard de URLSearchParams ( https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams )
function getQueryParamsObject() {
const searchParams = new URLSearchParams(location.search.slice(1));
return searchParams
? _.fromPairs(Array.from(searchParams.entries()))
: {};
}
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 pour des raisons de simplicité.
Il devrait être facile de créer une solution plus compatible puisque vous avez accès à searchParams.entries () iterator.
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¶m[]=8&othr_param=abc¶m[]=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;
}
Les solutions proposées que j'ai trouvées jusqu'à présent ne couvrent pas de scénarios plus complexes.
Je devais 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"
}
}
}
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;
};
Utilisation de ES6, des API URL et API APISearchSearch.
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;
}
ES6 One Liner
[...new URLSearchParams(location.search).entries()].reduce((prev, [key,val]) => {prev[key] = val; return prev}, {})
ES6 une doublure. Propre et simple.
var obj = [...new URLSearchParams(location.search).entries()].reduce((sum, [key,val]) => Object.assign({[key]:val}, sum), {});
Pour votre cas particulier:
Object.fromEntries(new URLSearchParams('abc=foo&def=%5Basf%5D&xyz=5'));
Pour le cas plus générique où quelqu'un veut analyser des paramètres de requête dans 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] }), {});
À ma connaissance, il n’existe pas de solution native. Dojo a une méthode de non-sérialisation intégrée si vous utilisez ce framework par hasard.
Sinon, vous pouvez le mettre en œuvre vous-même plutôt 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 ()
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;
}
}
}
Assez facile avec l’API Web URLSearchParams
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());
NOTE: non pris en charge dans IE}
Il existe une bibliothèque légère appelée YouAreI.js qui a été 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' }
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 un 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 acceptera uniquement les paramètres, mais le plugin jQuery prendra l’URL complète et renverra les paramètres sérialisés.
Voici ma version rapide et incorrecte, qui consiste essentiellement à diviser les paramètres d'URL séparés par '&' en éléments de tableau, puis à itérer sur ce tableau en ajoutant des paires clé/valeur séparées par '=' dans un objet. J'utilise decodeURIComponent () pour traduire les caractères codés en équivalents chaînes 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')
résultats
{
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.
//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;
}
Si vous utilisez URI.js, vous pouvez utiliser:
https://medialize.github.io/URI.js/docs.html#static-parseQuery
var result = URI.parseQuery("?foo=bar&hello=world&hello=mars&bam=&yup");
result === {
foo: "bar",
hello: ["world", "mars"],
bam: "",
yup: null
};
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"]}
Manque les clés, 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 génèrent une erreur de syntaxe sur cette URL loufoque:?a=aa&b=bb&c=&=dd&e
Object {a: "aa", b: "bb", c: ""}
J'avais également besoin de traiter +
dans la partie requête de l'URL ( decodeURIComponent not ), j'ai donc adapté le code de Wolfgang pour qu'il devienne:
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 les paramètres de formulaire prêts pour l'URL, puis cette astuce pour créer un objet à partir de celui-ci. Je peux ensuite facilement mettre à jour les paramètres sur l'objet et reconstruire l'URL de 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);
Pour Node, vous pouvez utiliser les éléments suivants:
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
Construit sur 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 des paramètres séparés par des virgules (foo=bar,baz,bin
). Il vous permet également de rechercher une clé de requête donnée.
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"]
}
PREMIER U BESOIN DE DÉFINIR QU'EST-CE QU'UN 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 de 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]];
}