Codificación de cadena de consulta de un objeto Javascript

482

¿Conoces una forma rápida y sencilla de codificar un objeto Javascript en un objeto stringque pueda pasar a través de una GETsolicitud?

No jQuery, no hay otros marcos, simplemente Javascript :)

napolux
fuente
¿Por qué JQuery no puede ser una solución si hay una adecuada para su solución?
eaglei22
@ eaglei22 porque en ese momento estaba trabajando en un proyecto para un dispositivo decodificador IPTV y no se permitían bibliotecas externas. ;-)
napolux
1
Gracias por la respuesta. Veo esta especificación de vez en cuando y siempre me pregunté por qué. Bueno, ahora tengo uno, ¡gracias! :)
eaglei22
99
@ eaglei22 Porque a veces no desea cargar una biblioteca grande para obtener un elemento por id.
Aaron Harun
la mayoría de los navegadores son compatibles URLSearchParamsahora ...
mb21

Respuestas:

810

¿Me gusta esto?

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

Editar: este también convierte objetos recursivos (usando la notación php "array" para la cadena de consulta)

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

usuario187291
fuente
2
¿No se romperá dado {foo: [1,2,3], barra: "100%"}?
Quentin
1
@ Ofri: Para las solicitudes POST a un servidor configurado para recibirlo, JSON es una buena opción. Para solicitudes GET, si está enviando algo más que unos pocos parámetros simples al servidor, entonces es probable que su diseño sea incorrecto.
Tim Down
2
@Marcel Eso se debe a que la función no comprueba hasOwnProperty. He actualizado tu violín, así que ahora lo hace: jsfiddle.net/rudiedirkx/U5Tyb/1
Rudie
1
@TimDown Con respecto a su comentario enviando parámetros simples en las solicitudes GET. No estoy de acuerdo. La agrupación de parámetros en matrices podría resultar útil ya que PHP en el lado del servidor encuentra una matriz asociativa lista para funcionar. No puedo ver por qué esto está mal como diseño.
Savas Vedova
1
¿Es necesario el 'if (obj.hasOwnProperty (prop))'? El bucle de instrucción for in justo encima de las propiedades del objeto, por lo que llamar a hasOwnProperty siempre se evalúa como verdadero
Arnon
231

jQuery tiene una función para esto, jQuery.param()si ya lo está usando, puede usarlo: http://api.jquery.com/jquery.param/

ejemplo:

var params = { width:1680, height:1050 };
var str = jQuery.param( params );

str ahora contiene width=1680&height=1050

benvds
fuente
119
citando a Napolux (el OP): "simplemente Javascript" . : P
Sk8erPeter
66
jQuery.param () tiene un comportamiento siniestro. Intenta ejecutar var a = []; a [2564] = 12; console.log (jQuery.param ({proprieylist: a})); para ver a qué me refiero.
akond
13
@akond La documentación de jQuery dice específicamente que no puede pasar en una matriz desnuda.
Ariel
44
@Ariel Él no está pasando en una serie desnuda. Está pasando una matriz con solo un valor en el índice 2564. Para demostrar: var a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); Resultados en "parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo". Lo cual, aunque correcto, puede no ser lo que esperas.
Chris Hall
44
La pregunta ha formulado específicamente Vanilla JS
Bug Hunter 219
192

Simplemente use URLSearchParamsEsto funciona en todos los navegadores actuales

new URLSearchParams(object).toString()
nullaber
fuente
55
No, ya que no hace objetos recursivos
Eddie Monge Jr
No funciona en objetos anidados. let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
hitautodestruct
20
@EddieMongeJr Las cadenas de consulta son pares clave-valor por diseño, ni siquiera debería querer serializar objetos anidados. Esta respuesta es la forma moderna de hacerlo. Se necesitan votos a favor.
Romain Durand
55
Sí, son pares de valores clave, pero no hay nada que diga que el valor no puede ser un objeto codificado en cadena. Además, las preguntas originales piden un "Objeto Javascript en una cadena", que puede tener propiedades anidadas
Eddie Monge Jr
@EddieMongeJr incluso la respuesta aceptada (y las otras después de una breve mirada) no admite objetos anidados. Puedes stringifylos objetos anidados antes de que puedasURLSearchParams
Mosh Feu
128
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

Editar: Me gusta esta frase, pero apuesto a que sería una respuesta más popular si coincidía semánticamente con la respuesta aceptada:

function serialize( obj ) {
    let str = '?' + Object.keys(obj).reduce(function(a, k){
        a.push(k + '=' + encodeURIComponent(obj[k]));
        return a;
    }, []).join('&');
    return str;
}
sergk
fuente
1
Sin embargo, una línea dedicada para la función de reducción mejoraría en gran medida la legibilidad.
Aurelien Ribon
54
Usando .map () en lugar de .reduce () sería aún más simple: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Janes
2
Solo para tener en cuenta que Object.keyssolo está disponible en IE> = 9
Johnston
55
Más código de @Jannes mejorado usando plantillas ES6 en lugar de concatenación -Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
csilk
1
En caso de que sus claves necesiten encodeUriComponent ❤️ también: Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Blaise el
112

Aquí hay una línea en ES6:

Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
Nico Tejera
fuente
reemplace la llave con k y estará dorado
Jamie Kudla
17
¡Advertencia! Esto solo funciona en objetos poco profundos. Si tiene una propiedad de nivel superior que es otro objeto, este revestimiento generará "clave =% 5Bobject% 20Object% 5D". Solo como un aviso.
Andrew Allbright
44
Además, esto no escupe matrices. Llegué export?actions[]=finance,create,editcuando debería tener export?actions[]=finance&actions[]=create&actions[]=editcomo es el horrible estándar.
darkbluesun
3
Las matrices son casi siempre "estás solo" porque los argumentos de URL son solo cadenas en lo que respecta a las especificaciones, por lo que estás en el gancho de hacer que el servidor lea correctamente cualquier cosa que no sea una sola cadena estas llamando actions[]es notación PHP; Django usa múltiples en su actionlugar (sin []sufijo); algunos otros ORM / CMS requieren listas separadas por comas, etc. Entonces, "si no se trata de cadenas simples, primero asegúrese de saber lo que su servidor quiere".
Mike 'Pomax' Kamermans el
Solución muy elegante!
Anh Tran
51

Con Node.js v6.6.3

const querystring = require('querystring')

const obj = {
  foo: 'bar',
  baz: 'tor'
}

let result = querystring.stringify(obj)
// foo=bar&baz=tor

Referencia: https://nodejs.org/api/querystring.html

Lucas Constantino Silva
fuente
8
Esto no debería ser rechazado IMO, si es JS en el servidor, esta debería ser la respuesta correcta.
Michael Benin
44
Parece que no admite objetos anidados.
Yarin Gold el
45

Sugiero usar la URLSearchParamsinterfaz:

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

O pasando el objeto de búsqueda al constructor así:

const obj = {foo: "hi there", bar: "100%" };
const params = new URLSearchParams(obj).toString();
bmaggi
fuente
1
Sugerencia interesante, pero tenga en cuenta que el soporte del navegador para esta característica todavía es muy irregular.
mrec
Si no va a admitir IE (que es bastante común ahora) y algunas versiones móviles específicas, esta es la mejor respuesta, ya que es JavaScript simple.
Marcos Sandrini el
24

Una pequeña enmienda a la solución aceptada por el usuario187291:

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 comprobación de hasOwnProperty en el objeto hace que JSLint / JSHint esté contento, y evita la serialización accidental de métodos del objeto u otras cosas si el objeto no es un simple diccionario. Consulte el párrafo para ver las declaraciones en esta página: http://javascript.crockford.com/code.html

jssebastian
fuente
14

Bueno, todos parecen poner su frase aquí, así que aquí va la mía:

const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
Alex Escalante
fuente
1
Object.entries no es compatible con IE.
MBouwman
@MBouwman, por supuesto, IE está roto más allá del bien y del mal, es por eso que debes usar babel / core-js
chpio
@chpio Babel / core-js no admite Object.entries si tengo razón.
MBouwman
core tiene soporte para Object.entries: github.com/zloirock/core-js/blob/master/… e incluso la antigua transformación corejs2 babel runtime también lo admite github.com/babel/babel/blob/…
chpio
12

¿Necesitas enviar objetos arbitrarios? Si es así, GET es una mala idea, ya que hay límites en la longitud de las URL que los agentes de usuario y los servidores web aceptarán. Mi sugerencia sería crear una matriz de pares de nombre-valor para enviar y luego crear una cadena de consulta:

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
fuente
11

Rails / PHP Style Query Builder

Este método convierte un objeto Javascript en a URI Query String. También maneja matrices y objetos anidados (en Rails/ PHPsintaxis):

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

Ejemplo de uso:

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
fuente
Buen ejemplo Arreglé un error tipográfico en tu respuesta. Por cierto, sería interesante si edita sus valores de functionexclusión falsy(nulo, indefinido, NaN, '') ...
developer033
8

usa JSON.

Eche un vistazo a esta pregunta para obtener ideas sobre cómo implementarla.

Ofri Raviv
fuente
2
No sé en qué está escribiendo el servidor, pero la mayoría de los idiomas modernos tienen buenos paquetes que leen JSON. Además, incluso si termina implementándolo, es mejor implementar un código de servidor de lectura JSON que inventar un nuevo esquema de codificación propio. Las codificaciones de bricolaje como esta tienden a tener errores (porque generalmente no piensas en todos los casos posibles, como que el valor sea una matriz en sí mismo, etc.).
Ofri Raviv el
¿básicamente está sugiriendo convertir el objeto en JSON y luego pasar toda la cadena JSON al servidor como un único parámetro de consulta GET?
Marco Demaio
8

Aquí está la versión coffeescript de la respuesta aceptada. Esto podría ahorrarle tiempo a alguien.

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
fuente
Gracias alfonso! Realmente me salvó el tiempo!
Lukas
6

Aquí hay una versión concisa y recursiva con Object.entries . Maneja matrices anidadas arbitrariamente, pero no objetos anidados. También elimina elementos vacíos:

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

P.ej:

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
fuente
Esta versión hizo el trabajo por mí cuando se trata de matrices anidadas. Hizo un pequeño ajuste para usar las teclas de matriz de estilo Ruby / PHP, pero por lo demás funciona muy bien.
nickb
5

Este omite valores nulos / indefinidos

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
fuente
5

En ES7 puedes escribir esto en una línea:

const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
Pavlo Sadovyi
fuente
4

Línea única para convertir Objeto en Cadena de Consulta en caso de que alguien lo necesite nuevamente

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
fuente
4

Tengo una solución más simple que no utiliza ninguna biblioteca de terceros y ya es apta para ser utilizada en cualquier navegador que tenga "Object.keys" (también conocido como todos los navegadores modernos + edge + ie):

En ES5

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

En ES3

function(a){
    if( typeof(a) !== 'object' ) 
        return '';
    return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&');
}
LeandroLuk
fuente
3

Si desea convertir un objeto anidado de forma recursiva y el objeto puede contener o no matrices (y las matrices pueden contener objetos o matrices, etc.), entonces la solución se vuelve un poco más compleja. Este es mi intento.

También he agregado algunas opciones para elegir si desea grabar para cada miembro del objeto a qué profundidad en el objeto principal se encuentra, y para elegir si desea agregar una etiqueta a los miembros que provienen de matrices convertidas.

Idealmente, debe probar si el parámetro cosa realmente recibe un objeto o una matriz.

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
fuente
Gracias por el enfoque recursivo
Sherlock
3

Además de la solución aceptada, esto funciona con objetos y matriz de objetos:

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

También ha agregado objName si está utilizando parámetros de objeto como en los métodos de acción asp.net mvc.

A.Aziem Moemen
fuente
3

Un poco se ve mejor

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
fuente
3

Hice una comparación de stringifiers JSON y los resultados son los siguientes:

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

El más corto entre ellos es la notación de objeto URL .

niutech
fuente
2

ok, es una publicación anterior pero estoy enfrentando este problema y he encontrado mi solución personal ... tal vez pueda ayudar a alguien más ...

     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
fuente
2

Las respuestas anteriores no funcionan si tiene muchos objetos anidados. En su lugar, puede elegir la función param desde aquí: https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js ¡ Funcionó muy bien para mí!

    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
fuente
2

SOLUCIÓN ES6 PARA LA CODIFICACIÓN DE HERRAMIENTAS DE CONSULTA DE UN OBJETO 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
fuente
2

Esta es una solución que funcionará para los backends .NET listos para usar. Tomé la respuesta principal de este hilo y la actualicé para satisfacer nuestras necesidades .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
fuente
1

He escrito un paquete solo para eso: object-query-string :)

Admite objetos anidados, matrices, funciones de codificación personalizadas, etc. Ligero y sin 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'
});

devoluciones

filter[brands][]=Audi&filter[models][]=A4&filter[models][]=A6&filter[models][]=A8&filter[accidentFree]=true&sort=milage
dayvee.cz
fuente
0

Solo otra forma (sin objeto recursivo):

   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
fuente
0

Consulte la respuesta @ user187291, agregue "isArray" como parámetro para hacer que la matriz anidada json se convierta.

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

                }

Para hacer el resultado:

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);
Guardabosques largos
fuente
0

También puede lograr esto usando 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
fuente
1
Este es un buen ejercicio, pero es al revés. No es una respuesta a la pregunta.
Christiaan Westerbeek