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


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


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


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

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

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

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


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

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


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

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

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

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.


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("&")

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"

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('&');
}

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('&'))

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

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('&');
}

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;

}

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.


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("&");
}

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":"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 .


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

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

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"

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

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

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

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

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


1
C'est un bon exercice, mais c'est l'inverse. Pas une réponse à la question.
Christiaan Westerbeek
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.