Connaissez-vous un moyen rapide et simple d'encoder un objet Javascript dans un objet string
que je peux transmettre via une GET
requête?
Non jQuery
, pas d'autres cadres - juste du Javascript simple :)
URLSearchParams
maintenant ...
Connaissez-vous un moyen rapide et simple d'encoder un objet Javascript dans un objet string
que je peux transmettre via une GET
requête?
Non jQuery
, pas d'autres cadres - juste du Javascript simple :)
URLSearchParams
maintenant ...
Réponses:
comme ça?
serialize = function(obj) {
var str = [];
for (var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
console.log(serialize({
foo: "hi there",
bar: "100%"
}));
// foo=hi%20there&bar=100%25
Edit: celui-ci convertit également les objets récursifs (en utilisant la notation "tableau" php pour la chaîne de requête)
serialize = function(obj, prefix) {
var str = [],
p;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
var k = prefix ? prefix + "[" + p + "]" : p,
v = obj[p];
str.push((v !== null && typeof v === "object") ?
serialize(v, k) :
encodeURIComponent(k) + "=" + encodeURIComponent(v));
}
}
return str.join("&");
}
console.log(serialize({
foo: "hi there",
bar: {
blah: 123,
quux: [1, 2, 3]
}
}));
// foo=hi%20there&bar%5Bblah%5D=123&bar%5Bquux%5D%5B0%5D=1&bar%5Bquux%5D%5B1%5D=2&bar%5Bquux%5D%5B2%5D=3
jQuery a une fonction pour cela, jQuery.param()
si vous l'utilisez déjà, vous pouvez l'utiliser:
http://api.jquery.com/jquery.param/
exemple:
var params = { width:1680, height:1050 };
var str = jQuery.param( params );
str
contient maintenant width=1680&height=1050
var a = []; a[5] = 'foo'; jQuery.param({ parameters: a });
Résultats en "parameters[]=¶meters[]=¶meters[]=¶meters[]=¶meters[]=¶meters[]=foo"
. Ce qui, bien que correct, peut ne pas être ce que vous attendez.
Utilisez simplement URLSearchParams
ceci fonctionne dans tous les navigateurs actuels
new URLSearchParams(object).toString()
let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
stringify
les objets imbriqués avant de pouvoirURLSearchParams
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
Edit: J'aime ce one-liner, mais je parie que ce serait une réponse plus populaire s'il correspondait sémantiquement à la réponse acceptée:
function serialize( obj ) {
let str = '?' + Object.keys(obj).reduce(function(a, k){
a.push(k + '=' + encodeURIComponent(obj[k]));
return a;
}, []).join('&');
return str;
}
Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Object.keys
n'est disponible que dans IE> = 9
Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Voici une doublure dans ES6:
Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
export?actions[]=finance,create,edit
quand il aurait dû, export?actions[]=finance&actions[]=create&actions[]=edit
comme c'est la norme horrible.
actions[]
est la notation PHP; Django utilise plusieurs à la action
place (pas de []
suffixe); certains autres ORM / CMS nécessitent des listes séparées par des virgules, etc. Donc "si ce ne sont pas de simples chaînes, assurez-vous d'abord de savoir ce que votre serveur veut même".
const querystring = require('querystring')
const obj = {
foo: 'bar',
baz: 'tor'
}
let result = querystring.stringify(obj)
// foo=bar&baz=tor
Référence: https://nodejs.org/api/querystring.html
Je suggère d'utiliser l' URLSearchParams
interface:
const searchParams = new URLSearchParams();
const search = {foo: "hi there", bar: "100%" };
Object.keys(search).forEach(key => searchParams.append(key, search[key]));
console.log(searchParams.toString())
Ou en passant l'objet de recherche au constructeur comme ceci:
const obj = {foo: "hi there", bar: "100%" };
const params = new URLSearchParams(obj).toString();
Un petit amendement à la solution acceptée par user187291:
serialize = function(obj) {
var str = [];
for(var p in obj){
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
}
return str.join("&");
}
La vérification de hasOwnProperty sur l'objet rend JSLint / JSHint heureux et empêche les méthodes de sérialisation accidentelles de l'objet ou d'autres choses si l'objet n'est rien d'autre qu'un simple dictionnaire. Voir le paragraphe sur pour les déclarations sur cette page: http://javascript.crockford.com/code.html
Eh bien, tout le monde semble mettre son one-liner ici alors voici le mien:
const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
Avez-vous besoin d'envoyer des objets arbitraires? Si c'est le cas, GET est une mauvaise idée car il existe des limites à la longueur des URL que les agents utilisateurs et les serveurs Web acceptent. Ma suggestion serait de créer un tableau de paires nom-valeur à envoyer, puis de créer une chaîne de requête:
function QueryStringBuilder() {
var nameValues = [];
this.add = function(name, value) {
nameValues.push( {name: name, value: value} );
};
this.toQueryString = function() {
var segments = [], nameValue;
for (var i = 0, len = nameValues.length; i < len; i++) {
nameValue = nameValues[i];
segments[i] = encodeURIComponent(nameValue.name) + "=" + encodeURIComponent(nameValue.value);
}
return segments.join("&");
};
}
var qsb = new QueryStringBuilder();
qsb.add("veg", "cabbage");
qsb.add("vegCount", "5");
alert( qsb.toQueryString() );
Cette méthode convertit un objet Javascript en un URI Query String
. Gère également les tableaux et objets imbriqués (dans Rails
/ PHP
syntaxe):
function serializeQuery(params, prefix) {
const query = Object.keys(params).map((key) => {
const value = params[key];
if (params.constructor === Array)
key = `${prefix}[]`;
else if (params.constructor === Object)
key = (prefix ? `${prefix}[${key}]` : key);
if (typeof value === 'object')
return serializeQuery(value, key);
else
return `${key}=${encodeURIComponent(value)}`;
});
return [].concat.apply([], query).join('&');
}
Exemple d'utilisation:
let params = {
a: 100,
b: 'has spaces',
c: [1, 2, 3],
d: { x: 9, y: 8}
}
serializeQuery(params)
// returns 'a=100&b=has%20spaces&c[]=1&c[]=2&c[]=3&d[x]=9&d[y]=8
function
pour exclure les falsy
valeurs (null, undefined, NaN, '') ...
utilisez JSON.
jetez un oeil à cette question pour des idées sur la façon de mettre en œuvre.
Voici la version coffeescript de la réponse acceptée. Cela pourrait faire gagner du temps à quelqu'un.
serialize = (obj, prefix) ->
str = []
for p, v of obj
k = if prefix then prefix + "[" + p + "]" else p
if typeof v == "object"
str.push(serialize(v, k))
else
str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v))
str.join("&")
Voici une version concise et récursive avec Object.entries . Il gère les tableaux imbriqués arbitrairement, mais pas les objets imbriqués. Il supprime également les éléments vides:
const format = (k,v) => v !== null ? `${k}=${encodeURIComponent(v)}` : ''
const to_qs = (obj) => {
return [].concat(...Object.entries(obj)
.map(([k,v]) => Array.isArray(v)
? v.map(arr => to_qs({[k]:arr}))
: format(k,v)))
.filter(x => x)
.join('&');
}
Par exemple:
let json = {
a: [1, 2, 3],
b: [], // omit b
c: 1,
d: "test&encoding", // uriencode
e: [[4,5],[6,7]], // flatten this
f: null, // omit nulls
g: 0
};
let qs = to_qs(json)
=> "a=1&a=2&a=3&c=1&d=test%26encoding&e=4&e=5&e=6&e=7&g=0"
Dans ES7, vous pouvez écrire ceci sur une seule ligne:
const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
Une seule ligne pour convertir l'objet en chaîne de requête au cas où quelqu'un en aurait encore besoin
let Objs = { a: 'obejct-a', b: 'object-b' }
Object.keys(objs).map(key => key + '=' + objs[key]).join('&')
// result will be a=object-a&b=object-b
J'ai une solution plus simple qui n'utilise aucune bibliothèque tierce et est déjà apte à être utilisée dans n'importe quel navigateur qui a "Object.keys" (aka tous les navigateurs modernes + edge + ie):
Dans ES5
function(a){
if( typeof(a) !== 'object' )
return '';
return `?${Object.keys(a).map(k=>`${k}=${a[k]}`).join('&')}`;
}
Dans ES3
function(a){
if( typeof(a) !== 'object' )
return '';
return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
}
Si vous souhaitez convertir un objet imbriqué de manière récursive et que l'objet peut ou non contenir des tableaux (et que les tableaux peuvent contenir des objets ou des tableaux, etc.), la solution devient un peu plus complexe. Ceci est ma tentative.
J'ai également ajouté quelques options pour choisir si vous souhaitez enregistrer pour chaque membre d'objet à quelle profondeur dans l'objet principal il se trouve, et pour choisir si vous souhaitez ajouter une étiquette aux membres provenant de tableaux convertis.
Idéalement, vous devriez tester si le paramètre de chose reçoit vraiment un objet ou un tableau.
function thingToString(thing,maxDepth,recordLevel,markArrays){
//thing: object or array to be recursively serialized
//maxDepth (int or false):
// (int) how deep to go with converting objects/arrays within objs/arrays
// (false) no limit to recursive objects/arrays within objects/arrays
//recordLevel (boolean):
// true - insert "(level 1)" before transcript of members at level one (etc)
// false - just
//markArrays (boolean):
// insert text to indicate any members that came from arrays
var result = "";
if (maxDepth !== false && typeof maxDepth != 'number') {maxDepth = 3;}
var runningDepth = 0;//Keeps track how deep we're into recursion
//First prepare the function, so that it can call itself recursively
function serializeAnything(thing){
//Set path-finder values
runningDepth += 1;
if(recordLevel){result += "(level " + runningDepth + ")";}
//First convert any arrays to object so they can be processed
if (thing instanceof Array){
var realObj = {};var key;
if (markArrays) {realObj['type'] = "converted array";}
for (var i = 0;i < thing.length;i++){
if (markArrays) {key = "a" + i;} else {key = i;}
realObj[key] = thing[i];
}
thing = realObj;
console.log('converted one array to ' + typeof realObj);
console.log(thing);
}
//Then deal with it
for (var member in thing){
if (typeof thing[member] == 'object' && runningDepth < maxDepth){
serializeAnything(thing[member]);
//When a sub-object/array is serialized, it will add one to
//running depth. But when we continue to this object/array's
//next sibling, the level must go back up by one
runningDepth -= 1;
} else if (maxDepth !== false && runningDepth >= maxDepth) {
console.log('Reached bottom');
} else
if (
typeof thing[member] == "string" ||
typeof thing[member] == 'boolean' ||
typeof thing[member] == 'number'
){
result += "(" + member + ": " + thing[member] + ") ";
} else {
result += "(" + member + ": [" + typeof thing[member] + " not supported]) ";
}
}
}
//Actually kick off the serialization
serializeAnything(thing);
return result;
}
Addition pour solution acceptée, cela fonctionne avec des objets et un tableau d'objets:
parseJsonAsQueryString = function (obj, prefix, objName) {
var str = [];
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
var v = obj[p];
if (typeof v == "object") {
var k = (objName ? objName + '.' : '') + (prefix ? prefix + "[" + p + "]" : p);
str.push(parseJsonAsQueryString(v, k));
} else {
var k = (objName ? objName + '.' : '') + (prefix ? prefix + '.' + p : p);
str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
//str.push(k + "=" + v);
}
}
}
return str.join("&");
}
Vous avez également ajouté objName si vous utilisez des paramètres d'objet comme dans les méthodes d'action asp.net mvc.
Un peu mieux
objectToQueryString(obj, prefix) {
return Object.keys(obj).map(objKey => {
if (obj.hasOwnProperty(objKey)) {
const key = prefix ? `${prefix}[${objKey}]` : objKey;
const value = obj[objKey];
return typeof value === "object" ?
this.objectToQueryString(value, key) :
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
}
return null;
}).join("&");
}
J'ai fait une comparaison des stringifiers JSON et les résultats sont les suivants:
JSON: {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":"$1,446.35","age":32,"name":"Logan Keller","email":"logankeller@artiq.com","phone":"+1 (952) 533-2258","friends":[{"id":0,"name":"Colon Salazar"},{"id":1,"name":"French Mcneil"},{"id":2,"name":"Carol Martin"}],"favoriteFruit":"banana"}
Rison: (_id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258')
O-Rison: _id:'5973782bdb9a930533b05cb2',age:32,balance:'$1,446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258'
JSURL: ~(_id~'5973782bdb9a930533b05cb2~isActive~true~balance~'!1*2c446.35~age~32~name~'Logan*20Keller~email~'logankeller*40artiq.com~phone~'*2b1*20*28952*29*20533-2258~friends~(~(id~0~name~'Colon*20Salazar)~(id~1~name~'French*20Mcneil)~(id~2~name~'Carol*20Martin))~favoriteFruit~'banana)
QS: _id=5973782bdb9a930533b05cb2&isActive=true&balance=$1,446.35&age=32&name=Logan Keller&email=logankeller@artiq.com&phone=+1 (952) 533-2258&friends[0][id]=0&friends[0][name]=Colon Salazar&friends[1][id]=1&friends[1][name]=French Mcneil&friends[2][id]=2&friends[2][name]=Carol Martin&favoriteFruit=banana
URLON: $_id=5973782bdb9a930533b05cb2&isActive:true&balance=$1,446.35&age:32&name=Logan%20Keller&email=logankeller@artiq.com&phone=+1%20(952)%20533-2258&friends@$id:0&name=Colon%20Salazar;&$id:1&name=French%20Mcneil;&$id:2&name=Carol%20Martin;;&favoriteFruit=banana
QS-JSON: isActive=true&balance=%241%2C446.35&age=32&name=Logan+Keller&email=logankeller%40artiq.com&phone=%2B1+(952)+533-2258&friends(0).id=0&friends(0).name=Colon+Salazar&friends(1).id=1&friends(1).name=French+Mcneil&friends(2).id=2&friends(2).name=Carol+Martin&favoriteFruit=banana
La plus courte d'entre elles est la notation d'objet URL .
ok, c'est un post plus ancien mais je suis confronté à ce problème et j'ai trouvé ma solution personnelle .. peut peut-être aider quelqu'un d'autre ..
function objToQueryString(obj){
var k = Object.keys(obj);
var s = "";
for(var i=0;i<k.length;i++) {
s += k[i] + "=" + encodeURIComponent(obj[k[i]]);
if (i != k.length -1) s += "&";
}
return s;
};
Les réponses ci-dessus ne fonctionnent pas si vous avez beaucoup d'objets imbriqués. Au lieu de cela, vous pouvez choisir le paramètre de fonction ici - https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js Cela a très bien fonctionné pour moi!
var param = function (a) {
var s = [], rbracket = /\[\]$/,
isArray = function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}, add = function (k, v) {
v = typeof v === 'function' ? v() : v === null ? '' : v === undefined ? '' : v;
s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
}, buildParams = function (prefix, obj) {
var i, len, key;
if (prefix) {
if (isArray(obj)) {
for (i = 0, len = obj.length; i < len; i++) {
if (rbracket.test(prefix)) {
add(prefix, obj[i]);
} else {
buildParams(prefix + '[' + (typeof obj[i] === 'object' ? i : '') + ']', obj[i]);
}
}
} else if (obj && String(obj) === '[object Object]') {
for (key in obj) {
buildParams(prefix + '[' + key + ']', obj[key]);
}
} else {
add(prefix, obj);
}
} else if (isArray(obj)) {
for (i = 0, len = obj.length; i < len; i++) {
add(obj[i].name, obj[i].value);
}
} else {
for (key in obj) {
buildParams(key, obj[key]);
}
}
return s;
};
return buildParams('', a).join('&').replace(/%20/g, '+');
};
SOLUTION ES6 POUR LE CODAGE DE CHAÎNE DE REQUÊTE D'UN OBJET JAVASCRIPT
const params = {
a: 1,
b: 'query stringify',
c: null,
d: undefined,
f: '',
g: { foo: 1, bar: 2 },
h: ['Winterfell', 'Westeros', 'Braavos'],
i: { first: { second: { third: 3 }}}
}
static toQueryString(params = {}, prefix) {
const query = Object.keys(params).map((k) => {
let key = k;
const value = params[key];
if (!value && (value === null || value === undefined || isNaN(value))) {
value = '';
}
switch (params.constructor) {
case Array:
key = `${prefix}[]`;
break;
case Object:
key = (prefix ? `${prefix}[${key}]` : key);
break;
}
if (typeof value === 'object') {
return this.toQueryString(value, key); // for nested objects
}
return `${key}=${encodeURIComponent(value)}`;
});
return query.join('&');
}
toQueryString (params)
"a=1&b=query%20stringify&c=&d=&f=&g[foo]=1&g[bar]=2&h[]=Winterfell&h[]=Westeros&h[]=Braavos&i[first][second][third]=3"
Il s'agit d'une solution qui fonctionnera pour les backends .NET prêts à l'emploi. J'ai pris la réponse principale de ce fil et l'ai mise à jour pour répondre à nos besoins .NET.
function objectToQuerystring(params) {
var result = '';
function convertJsonToQueryString(data, progress, name) {
name = name || '';
progress = progress || '';
if (typeof data === 'object') {
Object.keys(data).forEach(function (key) {
var value = data[key];
if (name == '') {
convertJsonToQueryString(value, progress, key);
} else {
if (isNaN(parseInt(key))) {
convertJsonToQueryString(value, progress, name + '.' + key);
} else {
convertJsonToQueryString(value, progress, name + '[' + key+ ']');
}
}
})
} else {
result = result ? result.concat('&') : result.concat('?');
result = result.concat(`${name}=${data}`);
}
}
convertJsonToQueryString(params);
return result;
}
J'ai écrit un paquet juste pour ça: chaîne de requête d'objet :)
Prend en charge les objets imbriqués, les tableaux, les fonctions d'encodage personnalisées, etc. Léger et sans jQuery.
// TypeScript
import { queryString } from 'object-query-string';
// Node.js
const { queryString } = require("object-query-string");
const query = queryString({
filter: {
brands: ["Audi"],
models: ["A4", "A6", "A8"],
accidentFree: true
},
sort: 'mileage'
});
Retour
filter[brands][]=Audi&filter[models][]=A4&filter[models][]=A6&filter[models][]=A8&filter[accidentFree]=true&sort=milage
Juste une autre façon (pas d'objet récursif):
getQueryString = function(obj)
{
result = "";
for(param in obj)
result += ( encodeURIComponent(param) + '=' + encodeURIComponent(obj[param]) + '&' );
if(result) //it's not empty string when at least one key/value pair was added. In such case we need to remove the last '&' char
result = result.substr(0, result.length - 1); //If length is zero or negative, substr returns an empty string [ref. http://msdn.microsoft.com/en-us/library/0esxc5wy(v=VS.85).aspx]
return result;
}
alert( getQueryString({foo: "hi there", bar: 123, quux: 2 }) );
Reportez-vous à la réponse @ user187291, ajoutez "isArray" comme paramètre pour effectuer la conversion du tableau imbriqué json.
data : {
staffId : "00000001",
Detail : [ {
"identityId" : "123456"
}, {
"identityId" : "654321"
} ],
}
Pour faire le résultat:
staffId = 00000001 & Detail [0] .identityId = 123456 & Detail [1] .identityId = 654321
serialize = function(obj, prefix, isArray) {
var str = [],p = 0;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
var k, v;
if (isArray)
k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
else
k = prefix ? prefix + "." + p + "" : p, v = obj[p];
if (v !== null && typeof v === "object") {
if (Array.isArray(v)) {
serialize(v, k, true);
} else {
serialize(v, k, false);
}
} else {
var query = k + "=" + v;
str.push(query);
}
}
}
return str.join("&");
};
serialize(data, "prefix", false);
Vous pouvez également y parvenir en utilisant du JavaScript simple .
const stringData = '?name=Nikhil&surname=Mahirrao&age=30';
const newData= {};
stringData.replace('?', '').split('&').map((value) => {
const temp = value.split('=');
newData[temp[0]] = temp[1];
});
console.log('stringData: '+stringData);
console.log('newData: ');
console.log(newData);