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

connaissez-vous un moyen simple et rapide pour encoder un objet Javascript dans un string que je peux passer via une requête GET ?

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

359
demandé sur Sheharyar 2009-11-11 15:07:37

28 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 aussi des objets récursifs (en utilisant la notation php "array" 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
656
répondu user187291 2018-03-05 13:08:03

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

204
répondu benvds 2017-04-12 11:50:05
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

Edit: j'aime bien ce one-liner, mais je parie qu'il serait plus populaires de répondre, s'il correspondait à la accepté de répondre du point de vue sémantique:

function serialize( obj ) {
  return '?'+Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
}
107
répondu sergk 2014-09-09 21:38:57

Voici une doublure en ES6:

Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
86
répondu Nico Tejera 2016-02-25 17:46:13

Avec Noeud.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

36
répondu Lucas Constantino Silva 2016-07-07 02:07:28

je suggère d'utiliser le 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())
23
répondu bmaggi 2017-06-17 20:48:58

un petit amendement à la solution acceptée par l'utilisateur 187291:

serialize = function(obj) {
   var str = [];
   for(var p in obj){
       if (obj.hasOwnProperty(p)) {
           str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
       }
   }
   return str.join("&");
}

vérifier pour hasOwnProperty sur l'objet rend JSLint / JSHint heureux, et il empêche accidentellement des méthodes de sérialisation de l'objet ou d'autres choses si l'objet est n'importe quoi mais un dictionnaire simple. Voir le paragraphe sur pour les déclarations dans cette page: http://javascript.crockford.com/code.html

22
répondu jssebastian 2013-02-26 18:50:31

avez-vous besoin d'envoyer des objets arbitraires? Si c'est le cas, GET est une mauvaise idée car il y a des limites à la longueur des URLs que les agents utilisateurs et les serveurs Web acceptent. Ma suggestion serait de construire un tableau de paires nom-valeur à envoyer, puis de construire 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() );
10
répondu Tim Down 2009-11-11 12:32:31

utilisez JSON.

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

10
répondu Ofri Raviv 2017-05-23 12:26:35

Voici la version coffeescript de accepted answer. Cela peut économiser 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("&")
9
répondu alf 2012-08-13 17:43:48

Rails / PHP Style Query Builder

cette méthode convertit un objet Javascript en un URI Query String . S'occupe également des tableaux et des objets imbriqués (dans la syntaxe Rails / PHP ):

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'Usage:

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
8
répondu Sheharyar 2017-04-29 21:18:28

Voici une version concise et récursive avec L'objet .les entrées . Il gère des tableaux imbriqués arbitrairement, mais pas des 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"
5
répondu mikebridge 2017-03-29 22:48:59

dans ES7 vous pouvez écrire ceci dans une ligne:

const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
5
répondu Pavlo Sadovyi 2018-01-31 16:13:34

Eh bien, tout le monde semble mettre son un paquetage ici donc ici il va le mien:

const encoded = Object.entries(obj).map(([k, v]) => `${k}=${v}`).join("&");
5
répondu Alex Escalante 2018-03-01 21:48:19

si vous voulez convertir un objet imbriqué de façon récursive et que l'objet peut ou non contenir des tableaux (et que les tableaux peuvent contenir des objets ou des tableaux, etc.), alors la solution devient un peu plus complexe. C'est ma tentative.

j'ai aussi ajouté quelques options pour choisir si vous voulez enregistrer pour chaque membre d'objet à quelle profondeur dans l'objet principal il se trouve, et pour choisir si vous voulez ajouter un label aux membres qui proviennent de tableaux convertis.

Idéalement, vous devriez tester si la chose paramètre vraiment reçoit 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;

}
3
répondu Wytze 2012-07-13 08:45:22

ok, c'est un post plus ancien mais je fais face à ce problème et j'ai trouvé ma solution personnelle.. peut-être peut 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;
     };
3
répondu hayatoShingu 2013-08-06 20:17:12

Plus pour la solution retenue, cela fonctionne avec les objets et 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("&");
}

ont également ajouté objName si vous utilisez des paramètres d'objet comme dans asp.net MVC action methods.

3
répondu A.Aziem Moemen 2016-06-02 01:55:43

un peu plus beau

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
répondu Pavel 2016-10-24 17:42:51

celle-ci saute 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('&');
}
3
répondu nimatra 2017-02-13 03:34:39

ligne simple pour convertir un objet en chaîne de requête au cas où quelqu'un en aurait besoin à nouveau

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
3
répondu Laravel Plus 2018-01-27 21:38:48

j'ai une solution plus simple qui n'utilise aucune bibliothèque tierce et qui est déjà apte à être utilisée dans n'importe quel navigateur qui a" objet.keys "(alias tous les navigateurs modernes + edge + ie):

Dans l'ES5

function(a){
    if( typeof(a) !== 'object' ) 
        return '';
    return `?${Object.keys(a).map(k=>`${k}=${a[k]}`).join('&')}`;
}

Dans l'ES3

function(a){
    if( typeof(a) !== 'object' ) 
        return '';
    return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
}
3
répondu LeandroLuk 2018-03-14 22:12:09

les réponses ci-dessus ne fonctionnent pas si vous avez beaucoup d'objets imbriqués. À la place, vous pouvez choisir la fonction param d'ici - https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js Ça 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
répondu Vandana Sharma 2017-01-19 13:22:36

j'ai fait un comparaison de JSON stringifiers et les résultats sont comme suit:

JSON:    {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":",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:',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:',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=,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=,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

le plus court d'entre eux est notation de L'objet URL .

2
répondu niutech 2018-04-25 00:50:07

il suffit d'utiliser le suivant: encodeURIComponent (JSON.stringify (obj))

// elastic search example
let story ={
  "query": {
    "bool": {
      "must": [
        {
          "term": { 
            "revision.published": 0, 
          }
        },
        {
          "term": { 
            "credits.properties.by.properties.name": "Michael Guild"
          }
        },
        {
          "nested": {
            "path": "taxonomy.sections",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "taxonomy.sections._id": "/science"
                    }
                  },
                  {
                    "term": {
                      "taxonomy.sections._website": "staging"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}


const whateva = encodeURIComponent(JSON.stringify(story))
console.log(whateva)
1
répondu Michael Guild 2018-07-20 22:22:08

Juste une autre façon (pas de récursive de l'objet):

   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
répondu Marco Demaio 2012-11-13 18:51:17

reportez-vous à partir de la réponse @user187291, ajouter "isArray" comme paramètre pour que le json tableau imbriqué à être converti.

data : {
                    staffId : "00000001",
                    Detail : [ {
                        "identityId" : "123456"
                    }, {
                        "identityId" : "654321"
                    } ],

                }

pour obtenir le résultat:

staffId=00000001&Detail [0].identityId=123456&Détail[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
répondu Long Ranger 2017-08-25 03:21:51

vous pouvez également atteindre cet objectif en utilisant simple JavaScript .

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);
0
répondu Nikhil Mahirrao 2018-01-12 06:23:29

const buildSortedQuery = (args) => {
    return Object.keys(args)
        .sort()
        .map(key => {
            return window.encodeURIComponent(key)
                + '='
                + window.encodeURIComponent(args[key]);
        })
        .join('&');
};

console.log(buildSortedQuery({
  foo: "hi there",
  bar: "100%"
}));

//bar=100%25&foo=hi%20there
0
répondu Anthony Zhan 2018-04-12 04:32:30