Codificação de string de consulta de um objeto Javascript

482

Você conhece uma maneira rápida e simples de codificar um objeto Javascript em um stringque eu possa passar por umGET solicitação?

Não jQuery, não há outras estruturas - apenas Javascript :)

napolux
fonte
Por que o JQuery não pode ser uma solução se existe uma apropriada para sua solução?
eaglei22
@ eaglei22 porque na época eu estava trabalhando em um projeto para um dispositivo de set-top box de IPTV e nenhuma biblioteca externa era permitida. ;-)
napolux 31/03
1
Obrigado pela resposta. Eu vejo essa especificação de tempos em tempos e sempre me perguntei por que um cenário. Bem, agora eu tenho um, obrigado! :)
eaglei22
9
@ eaglei22 Porque às vezes você não deseja carregar uma grande biblioteca para obter um elemento por ID.
Aaron Harun 26/06
a maioria dos navegadores URLSearchParams
oferece

Respostas:

810

como isso?

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: este também converte objetos recursivos (usando a notação php "array" para a string 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

user187291
fonte
2
Não vai quebrar dado {foo: [1,2,3], barra: "100%"}?
Quentin
1
@ Afri: Para solicitações POST para um servidor configurado para recebê-lo, o JSON é uma boa escolha. Para solicitações GET, se você estiver enviando algo além de alguns parâmetros simples para o servidor, é provável que seu design esteja errado.
Tim Baixo
2
@ Marcel Isso ocorre porque a função não verifica hasOwnProperty. Eu atualizei o seu violino por isso agora ele faz: jsfiddle.net/rudiedirkx/U5Tyb/1
Rudie
1
@ TimDown Em relação ao seu comentário, envie parâmetros simples nas solicitações GET. Eu não concordo. O agrupamento de parâmetros em matrizes pode ser útil, já que o PHP no lado do servidor encontra uma matriz associativa pronta para uso. Não vejo por que isso está errado como um design.
Savas Vedova
1
O 'if (obj.hasOwnProperty (prop))' é necessário? O hasOwnProperty no circuito de declaração apenas sobre as propriedades do objeto para chamar sempre avaliar a verdade
Arnon
231

O jQuery tem uma função para isso; jQuery.param()se você já estiver usando, pode usar isso: http://api.jquery.com/jquery.param/

exemplo:

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

str agora contém width=1680&height=1050

benvds
fonte
119
citando Napolux (o OP): "Javascript simples" . : P
Sk8erPeter
6
jQuery.param () tem um comportamento sinistro. Tente executar var a = []; a [2564] = 12; console.log (jQuery.param ({propertylist: a})); para ver o que eu quero dizer.
akond
13
@akond A documentação do jQuery diz especificamente que você não pode transmitir em uma matriz simples.
Ariel #
4
@ Ariel Ele não está passando em uma matriz nua. Ele está passando uma matriz com apenas um valor no índice 2564. Para demonstrar: var a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); Resultados em "parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo". Que, embora correto, pode não ser o que você espera.
Chris Salão
4
A pergunta foi feita especificamente ao Vanilla JS
Bug Hunter 219
192

Basta usar URLSearchParamsIsso funciona em todos os navegadores atuais

new URLSearchParams(object).toString()
nullaber
fonte
5
Não, uma vez que não faz objetos recursiva
Eddie Monge Jr
Não funciona no objeto aninhado. let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
Hitautodestruct
20
@EddieMongeJr As cadeias de consulta são pares de valores-chave por design, você nem deveria querer serializar objetos aninhados Essa resposta é o caminho moderno a seguir. Upvotes necessários.
Romain Durand
5
Sim, eles são pares de valores-chave, mas não há nada que indique que o valor não pode ser um objeto codificado em sequência. Além disso, as perguntas originais pede um "objeto JavaScript em uma string", que podem ter propriedades aninhadas
Eddie Monge Jr
@EddieMongeJr mesmo a resposta aceita (e as outras depois de uma breve olhada) não suportam objetos aninhados. Você pode stringifyos objetos aninhados antes de poderURLSearchParams
Mosh Feu
128
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')

Edit: Eu gosto deste one-liner, mas aposto que seria uma resposta mais popular se correspondesse à resposta aceita semanticamente:

function serialize( obj ) {
    let str = '?' + Object.keys(obj).reduce(function(a, k){
        a.push(k + '=' + encodeURIComponent(obj[k]));
        return a;
    }, []).join('&');
    return str;
}
sergk
fonte
1
Uma linha dedicada para a função de redução melhoraria bastante a legibilidade.
Aurelien Ribon
54
Usando .map () em vez de .reduce () seria ainda mais simples: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Janes
2
Apenas a nota que Object.keysestá disponível somente no IE> = 9
Johnston
5
Código @Jannes aprimorado ainda mais usando modelos ES6 em vez de concatenaçãoObject.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
#
1
Caso suas chaves também precisem de codificarUriComponent ❤️: Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Blaise
112

Aqui está um liner no ES6:

Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
Nico Tejera
fonte
substituir chave w / k e você é ouro
Jamie Kudla
17
Atenção! Isso funciona apenas em objetos rasos. Se você tiver uma propriedade de nível superior que é outro objeto, esse liner exibirá "key =% 5Bobject% 20Object% 5D". Assim como um alerta.
Andrew Allbright
4
Além disso, isso não gera arrays. Eu cheguei export?actions[]=finance,create,editquando deveria ter export?actions[]=finance&actions[]=create&actions[]=editcomo é o padrão terrível.
darkbluesun
3
As matrizes são praticamente sempre "você está por sua conta", porque os argumentos de URL são apenas cadeias de caracteres no que diz respeito às especificações, portanto, você está pronto para fazer com que qualquer coisa que não seja uma única sequência seja lida corretamente pelo servidor você está ligando. actions[]é notação PHP; O Django usa múltiplo action(sem []sufixo); alguns outros ORM / CMS exigem listas separadas por vírgula, etc.
Mike 'Pomax' Kamermans
Solução muito elegante!
Anh Tran
51

Com o Node.js v6.6.3

const querystring = require('querystring')

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

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

Referência: https://nodejs.org/api/querystring.html

Lucas Constantino Silva
fonte
8
Isso não deve ter o voto negativo da OMI, se for JS no servidor, essa deve ser a resposta correta.
Michael Benin
4
Parece que não suporta objetos aninhados.
Yarin Gold 01/01
44

Eu sugiro usar a 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 passando o objeto de pesquisa para o construtor como este:

const obj = {foo: "hi there", bar: "100%" };
const params = new URLSearchParams(obj).toString();
bmaggi
fonte
1
Sugestão interessante, mas saiba que o suporte ao navegador para esse recurso ainda é muito irregular.
MREC
Se você não suporta o IE (o que é bastante comum agora) e algumas versões móveis específicas, esta é a melhor resposta, pois é um JavaScript simples.
Marcos Sandrini
24

Uma pequena alteração à solução aceita pelo 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("&");
}

A verificação de hasOwnProperty no objeto deixa JSLint / JSHint feliz e impede a serialização acidental de métodos do objeto ou de outras coisas, se o objeto não for um dicionário simples. Consulte o parágrafo em para instruções nesta página: http://javascript.crockford.com/code.html

jssebastian
fonte
14

Bem, todo mundo parece colocar sua frase aqui, então aqui vai a minha:

const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
Alex Escalante
fonte
1
Object.entries não é suportado no IE.
precisa saber é o seguinte
@MBouwman claro, IE está quebrado além do bem e do mal, é por isso que você tem que usar babel / Core-js
chpio
@chpio Babel / core-js não suporta Object.entries se eu estiver certo.
precisa saber é o seguinte
O core tem suporte para Object.entries: github.com/zloirock/core-js/blob/master/… e até mesmo a antiga conversão de tempo de execução do corejs2 babel também suporta github.com/babel/babel/blob/…
chpio
12

Você precisa enviar objetos arbitrários? Nesse caso, GET é uma péssima idéia, pois há limites para os comprimentos de URLs que os agentes do usuário e os servidores da web aceitarão. Minha sugestão seria criar uma matriz de pares nome-valor para enviar e, em seguida, criar uma string 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
fonte
11

Construtor de consultas de estilo Rails / PHP

Este método converte um objeto Javascript em um URI Query String. Também lida com matrizes e objetos aninhados (na Rails/ PHPsintaxe):

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

Exemplo 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
fonte
Belo exemplo. Corrigi um erro de digitação na sua resposta. By the way, seria interessante se você editar o seu functionpara excluir falsyvalores (nulo, indefinido, NaN, '') ...
developer033
8

use JSON.

dê uma olhada nesta pergunta para obter idéias sobre como implementar.

Ofri Raviv
fonte
2
Não sei no que ele está escrevendo o servidor, mas a maioria das linguagens modernas tem bons pacotes que lêem JSON. Além disso, mesmo que ele acabe implementando, é melhor implementar um código de servidor de leitura JSON do que inventar um novo esquema de codificação. Codificações DIY como essa tendem a ser de buggy (porque você geralmente não pensa em todos os casos possíveis, como o valor sendo uma matriz em si etc ').
Ofri Raviv
você está basicamente sugerindo converter o objeto em JSON e depois passar toda a string JSON para o servidor como um único parâmetro de consulta GET?
Marco Demaio 13/11/2012
8

Aqui está a versão coffeescript da resposta aceita. Isso pode economizar tempo para alguém.

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
fonte
Obrigado Alfonso! Realmente economizou meu tempo!
Lukas
6

Aqui está uma versão concisa e recursiva com Object.entries . Ele lida com matrizes aninhadas arbitrariamente, mas não com objetos aninhados. Ele também remove elementos vazios:

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

Por exemplo:

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
fonte
Esta versão fez o trabalho para mim ao lidar com matrizes aninhadas. Fiz um pequeno ajuste para usar chaves de matriz no estilo Ruby / PHP, mas, caso contrário, funciona muito bem.
Nickb 27/11
5

Este pula 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
fonte
5

No ES7, você pode escrever isso em uma linha:

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

Linha única para converter Objeto em String de Consulta, caso alguém precise dela novamente

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

Eu tenho uma solução mais simples que não usa nenhuma biblioteca de terceiros e já pode ser usada em qualquer navegador que tenha "Object.keys" (também conhecido como todos os navegadores modernos + borda + ou seja):

No ES5

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

No ES3

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

Se você deseja converter um objeto aninhado recursivamente e o objeto pode ou não conter matrizes (e as matrizes podem conter objetos ou matrizes, etc.), a solução fica um pouco mais complexa. Esta é a minha tentativa.

Também adicionei algumas opções para escolher se você deseja gravar para cada membro do objeto em que profundidade do objeto principal ele se encontra e para escolher se deseja adicionar um rótulo aos membros provenientes de matrizes convertidas.

Idealmente, você deve testar se o parâmetro thing realmente recebe um objeto ou 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
fonte
Obrigado pela abordagem recursiva
Sherlock
3

Além da solução aceita, isso funciona com objetos e 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("&");
}

Também adicionamos objName se você estiver usando parâmetros de objeto, como nos métodos de ação asp.net mvc.

A.Aziem Moemen
fonte
3

Um pouco melhor

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

Fiz uma comparação dos stringifiers JSON e os resultados são os seguintes:

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

O menor deles é a URL Object Notation .

niutech
fonte
2

ok, é um post antigo, mas estou enfrentando esse problema e encontrei minha solução pessoal .. talvez possa ajudar outra pessoa ..

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

As respostas acima não funcionam se você tiver muitos objetos aninhados. Em vez disso, você pode escolher a função param daqui - https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js Funcionou muito bem para mim!

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

SOLUÇÃO ES6 PARA A CODIFICAÇÃO DE CORDAS DE CONSULTA DE UM 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 (parâmetros)

"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
fonte
2

Esta é uma solução que funcionará para back-ends .NET prontos para uso. Peguei a resposta principal deste segmento e atualizei-o para atender às nossas necessidades de .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
fonte
1

Eu escrevi um pacote exatamente para isso: object-query-string :)

Suporta objetos aninhados, matrizes, funções de codificação personalizadas, etc. Leve e sem 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'
});

retorna

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

Apenas outra maneira (nenhum 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
fonte
0

Consulte a resposta @ user187291, adicione "isArray" como parâmetro para fazer com que a matriz aninhada json seja convertida.

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

                }

Para fazer o resultado:

staffId = 00000001 & Detalhe [0] .identityId = 123456 & Detalhe [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
fonte
0

Você também pode conseguir isso usando JavaScript simples .

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
fonte
1
Este é um bom exercício, mas é o contrário. Não é uma resposta para a pergunta.
Christiaan Westerbeek