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

Você conhece uma maneira rápida e simples de codificar um object JavaScript em uma string que eu possa passar por meio de uma solicitação GET ?

Não jQuery , sem outros frameworks – apenas JavaScript simples 🙂

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 

jQuery tem uma function para isso, jQuery.param() , se você já estiver usando, você 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

 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 a resposta aceita semanticamente:

 function serialize( obj ) { return '?'+Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&') } 

Aqui está um forro no ES6:

 Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&'); 

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

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 object deixa o JSLint / JSHint feliz e evita a serialização acidental de methods do object ou de outras coisas se o object não for um dictionary simples. Veja o parágrafo para obter instruções nesta página: http://javascript.crockford.com/code.html

Sugiro usar a interface URLSearchParams :

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

Você precisa enviar objects arbitrários? Em caso afirmativo, GET é uma má ideia, pois há limites para o tamanho das URLs que os agentes do usuário e os servidores da Web aceitarão. Minha sugestão seria criar uma matriz de pares de 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() ); 

use JSON.

Dê uma olhada nesta questão para idéias sobre como implementar.

Aqui está a versão do café 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("&") 

Construtor de Consultas de Estilo Rails / PHP

Esse método converte um object Javascript em uma URI Query String . Também lida com matrizes e objects nesteds (na syntax 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('&'); } 

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 

Bem, todo mundo parece colocar seu forro aqui, então aqui está o meu:

 const encoded = Object.entries(obj).map(([k, v]) => `${k}=${v}`).join("&"); 

Aqui está uma versão concisa e recursiva com Object.entries . Ele lida com matrizes arbitrariamente aninhadas, mas não com objects nesteds. 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" 

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

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

Se você deseja converter um object nested recursivamente e o object pode ou não conter matrizes (e os arrays podem conter objects ou matrizes, etc), a solução fica um pouco mais complexa. Esta é minha tentativa.

Eu também adicionei algumas opções para escolher se você deseja gravar para cada membro do object em que profundidade o object principal está, e para escolher se você deseja adicionar um label aos membros que vêm de matrizes convertidas.

Idealmente, você deve testar se o parâmetro thing realmente recebe um object ou array.

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

ok, é um post mais antigo, mas estou enfrentando esse problema e eu encontrei minha solução pessoal .. talvez possa ajudar alguém ..

  function objToQueryString(obj){ var k = Object.keys(obj); var s = ""; for(var i=0;i 

Além de solução aceita, isso funciona com objects e matriz de objects:

 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 adicionei objName se você estiver usando parâmetros de object como em methods de ação asp.net mvc.

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

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

Linha única para converter Object em String de consulta, caso alguém precise 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 

Eu tenho uma solução mais simples que não usa qualquer biblioteca de terceiros e já está apto a ser usado em qualquer navegador que tenha “Object.keys” (também conhecido como todos os navegadores modernos + edge + ie):

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

As respostas acima não funcionam se você tiver muitos objects nesteds. Em vez disso, você pode escolher a function param a partir 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, '+'); }; 

Fiz uma comparação de strings de JSON e os resultados são os seguintes:

 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 

O mais curto entre eles é a notação de object URL .

Apenas outra maneira (sem object 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 }) ); 

Consulte a resposta @ user187291, adicione “isArray” como parâmetro para tornar a matriz aninhada json a ser 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); 

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

Apenas use o seguinte: 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)