Encodage de chaîne de requête d'un objet Javascript

482

Connaissez-vous un moyen rapide et simple d'encoder un objet Javascript dans un objet stringque je peux transmettre via une GETrequête?

Non jQuery, pas d'autres cadres - juste du Javascript simple :)

napolux
la source
Pourquoi JQuery ne peut-il pas être une solution s'il existe une solution appropriée pour votre solution?
eaglei22
@ eaglei22 car à l'époque je travaillais sur un projet de décodeur IPTV et aucune bibliothèque externe n'était autorisée. ;-)
napolux
1
Merci pour la réponse. Je vois cette spécification de temps en temps et je me suis toujours demandé pourquoi. Eh bien, maintenant j'en ai un, merci! :)
eaglei22
9
@ eaglei22 Parce que parfois vous ne voulez pas charger une grande bibliothèque pour obtenir un élément par id.
Aaron Harun
la plupart des navigateurs prennent en charge URLSearchParamsmaintenant ...
mb21

Réponses:

810

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

user187291
la source
2
Ne se cassera-t-il pas étant donné {foo: [1,2,3], bar: "100%"}?
Quentin
1
@Ofri: Pour les requêtes POST à ​​un serveur configuré pour les recevoir, JSON est un bon choix. Pour les demandes GET, si vous envoyez autre chose que quelques paramètres simples au serveur, il est probable que votre conception soit incorrecte.
Tim Down
2
@Marcel C'est parce que la fonction ne vérifie pas hasOwnProperty. J'ai mis à jour votre violon, alors maintenant: jsfiddle.net/rudiedirkx/U5Tyb/1
Rudie
1
@TimDown Concernant votre commentaire, envoi de paramètres simples dans les requêtes GET. Je ne suis pas d'accord. Le regroupement des paramètres en tableaux peut s'avérer utile car PHP côté serveur trouve un tableau associatif prêt à l'emploi. Je ne vois pas pourquoi c'est mal comme design.
Savas Vedova
1
Le «si (obj.hasOwnProperty (prop))» est-il nécessaire? La boucle d'instruction for juste au-dessus des propriétés de l'objet, donc appeler hasOwnProperty est toujours évalué à true
Arnon
231

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

benvds
la source
119
citant Napolux (l'OP): "Javascript tout simplement" . : P
Sk8erPeter
6
jQuery.param () a un comportement sinistre. Essayez d'exécuter var a = []; a [2564] = 12; console.log (jQuery.param ({propertylist: a})); pour voir ce que je veux dire.
akond
13
@akond La documentation jQuery indique spécifiquement que vous ne pouvez pas passer dans un tableau nu.
Ariel
4
@Ariel Il ne passe pas dans un tableau nu. Il passe dans un tableau avec une seule valeur à l'index 2564. Pour démontrer: var a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); Résultats en "parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo". Ce qui, bien que correct, peut ne pas être ce que vous attendez.
Chris Hall
4
La question a spécifiquement demandé Vanilla JS
Bug Hunter 219
192

Utilisez simplement URLSearchParamsceci fonctionne dans tous les navigateurs actuels

new URLSearchParams(object).toString()
nullaber
la source
5
Non car il ne fait pas d'objets récursifs
Eddie Monge Jr
Ne fonctionne pas sur les objets imbriqués. let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
hitautodestruct
20
@EddieMongeJr Les chaînes de requête sont des paires clé-valeur par conception, vous ne devriez même pas vouloir sérialiser des objets imbriqués. Cette réponse est la voie à suivre moderne. Upvotes nécessaires.
Romain Durand
5
Oui, ce sont des paires de valeurs clés, mais rien ne dit que la valeur ne peut pas être un objet codé en chaîne. En outre, les questions d'origine demandent un "objet Javascript dans une chaîne", qui peut avoir des propriétés imbriquées
Eddie Monge Jr
@EddieMongeJr même la réponse acceptée (et les autres après un bref aperçu) ne prend pas en charge les objets imbriqués. Vous pouvez stringifyles objets imbriqués avant de pouvoirURLSearchParams
Mosh Feu
128
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;
}
sergk
la source
1
Une ligne dédiée pour la fonction de réduction améliorerait cependant considérablement la lisibilité.
Aurelien Ribon
54
Utiliser .map () au lieu de .reduce () serait encore plus simple: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Jannes
2
Juste pour noter que Object.keysn'est disponible que dans IE> = 9
Johnston
5
Amélioration du code @Jannes en utilisant des modèles ES6 au lieu de la concaténation -Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
csilk
1
Au cas où vos clés auraient besoin d'encodeUriComponent ❤️ aussi: Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Blaise
112

Voici une doublure dans ES6:

Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
Nico Tejera
la source
remplacez la clé w / k et vous êtes en or
Jamie Kudla
17
Attention! Cela ne fonctionne que sur les objets peu profonds. Si vous avez une propriété de niveau supérieur qui est un autre objet, cette doublure générera "clé =% 5Bobjet% 20Objet% 5D". Tout comme un avertissement.
Andrew Allbright
4
De plus, cela ne crache pas de tableaux. J'ai eu export?actions[]=finance,create,editquand il aurait dû, export?actions[]=finance&actions[]=create&actions[]=editcomme c'est la norme horrible.
darkbluesun
3
Les tableaux sont à peu près toujours «vous êtes tout seul» car les arguments d'URL ne sont que des chaînes en ce qui concerne la spécification, donc vous êtes prêt à faire en sorte que tout ce qui n'est pas une chaîne soit lu correctement par le serveur vous appelez. actions[]est la notation PHP; Django utilise plusieurs à la actionplace (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".
Mike 'Pomax' Kamermans
Solution très élégante!
Anh Tran
51

Avec Node.js v6.6.3

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

Lucas Constantino Silva
la source
8
Cela ne devrait pas être rétrogradé IMO, si c'est JS sur le serveur, cela devrait être la bonne réponse.
Michael Benin
4
Il semble qu'il ne prenne pas en charge les objets imbriqués.
Yarin Gold du
45

Je suggère d'utiliser l' URLSearchParamsinterface:

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();
bmaggi
la source
1
Suggestion intéressante, mais sachez que la prise en charge du navigateur pour cette fonctionnalité est encore très inégale.
mrec
Si vous ne supportez pas IE (ce qui est assez courant maintenant) et certaines versions mobiles spécifiques, c'est la meilleure réponse, car c'est du JavaScript simple.
Marcos Sandrini
24

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

jssebastian
la source
14

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("&");
Alex Escalante
la source
1
Object.entries n'est pas pris en charge dans IE.
MBouwman
@MBouwman bien sûr, IE est brisé au-delà du bien et du mal, c'est pourquoi vous devez utiliser babel / core-js
chpio
@chpio Babel / core-js ne prend pas en charge Object.entries si j'ai raison.
MBouwman
core prend en charge Object.entries: github.com/zloirock/core-js/blob/master/… et même l'ancienne transformation corejs2 babel runtime le prend également en charge github.com/babel/babel/blob/…
chpio
12

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() );
Tim Down
la source
11

Rails / PHP Style Query Builder

Cette méthode convertit un objet Javascript en un URI Query String. Gère également les tableaux et objets imbriqués (dans Rails/ PHPsyntaxe):

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
Sheharyar
la source
Bel exemple. J'ai corrigé une faute de frappe dans votre réponse. Soit dit en passant, serait intéressant si vous modifiez votre functionpour exclure les falsyvaleurs (null, undefined, NaN, '') ...
developer033
8

utilisez JSON.

jetez un oeil à cette question pour des idées sur la façon de mettre en œuvre.

Ofri Raviv
la source
2
Je ne sais pas dans quoi il écrit le serveur, mais la plupart des langages modernes ont de bons paquets qui lisent JSON. En outre, même s'il finit par l'implémenter, il vaut mieux implémenter un code serveur de lecture JSON que d'inventer un nouveau schéma de codage de votre choix. Les encodages de bricolage comme celui-ci ont tendance à être bogués (car vous ne pensez généralement pas à tous les cas possibles, comme la valeur étant un tableau en soi, etc.).
Ofri Raviv
suggérez-vous essentiellement de convertir l'objet en JSON, puis de passer la chaîne JSON entière au serveur en tant que paramètre de requête GET unique?
Marco Demaio
8

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("&")
alf
la source
Merci Alfonso! Vraiment sauvé mon temps!
Lukas
6

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"
mikebridge
la source
Cette version a fait le travail pour moi lorsqu'il s'agissait de tableaux imbriqués. A légèrement modifié pour utiliser les clés de tableau de style Ruby / PHP, mais fonctionne très bien autrement.
nickb
5

Celui-ci ignore les valeurs nulles / non définies

export function urlEncodeQueryParams(data) {
    const params = Object.keys(data).map(key => data[key] ? `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}` : '');
    return params.filter(value => !!value).join('&');
}
nimatra
la source
5

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('&'))
Pavlo Sadovyi
la source
4

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
Laravel Plus
la source
4

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('&');
}
LeandroLuk
la source
3

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;

}
Wytze
la source
Merci pour l'approche récursive
Sherlock
3

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.

A.Aziem Moemen
la source
3

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("&");
}
Pavel
la source
3

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":"[email protected]","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:'[email protected]',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:'[email protected]',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 .

niutech
la source
2

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;
     };
hayatoShingu
la source
2

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, '+');
};
Vandana Sharma
la source
2

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"
gandharv garg
la source
2

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;
}
Angel Venchev
la source
1

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
dayvee.cz
la source
0

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 }) );
Marco Demaio
la source
0

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);
Long Ranger
la source
0

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

Nikhil Mahirrao
la source
1
C'est un bon exercice, mais c'est l'inverse. Pas une réponse à la question.
Christiaan Westerbeek