sirve - matriz javascript
Codificación de cadena de consulta de un objeto Javascript (30)
Rails / PHP Style Query Builder
Este método convierte un objeto Javascript en una URI Query String
. También maneja arrays y objetos anidados (en la sintaxis de 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(''&'');
}
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
¿Conoces una forma rápida y sencilla de codificar un objeto Javascript en una string
que pueda pasar a través de una solicitud GET
?
No jQuery
, no hay otros frameworks - simplemente Javascript :)
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
Éste salta 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(''&'');
}
¿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
Edición: 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
¿Necesitas enviar objetos arbitrarios? Si es así, GET es una mala idea, ya que existen límites a la longitud de las URL que los agentes de usuario y los servidores web aceptan. Mi sugerencia sería construir una matriz de pares nombre-valor para enviar y luego construir 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() );
¿Se puede utilizar URLSearchParams
?
solo new URLSearchParams(object).toString()
Chrome 49+, aunque
Además de la solución aceptada, esto funciona con los objetos y la 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á usando parámetros de objeto como en los métodos de acción de mvc de asp.net.
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("&")
Aquí hay un forro en ES6:
Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join(''&'');
Aquí hay una versión concisa y recursiva con Object.entries . Maneja matrices arbitrariamente anidadas, 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"
Bueno, todos parecen poner su liner aquí, así que aquí va el mío:
const encoded = Object.entries(obj).map((k, v) => `${k}=${encodeURIComponent(v)}`).join("&");
Consulte la respuesta @ user187291, agregue "isArray" como parámetro para hacer que la matriz anidada de 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);
En ES7 puedes escribir esto en una línea:
const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join(''='')).join(''&''))
Hice una comparación de los Strifiers de 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 protected]&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 protected]&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 objetos URL .
Línea única para convertir objetos en una 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
Las respuestas anteriores no completan el trabajo 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, ''+'');
};
Si desea convertir un objeto anidado de forma recursiva y el objeto puede o no contener arreglos (y los arreglos pueden contener objetos o arreglos, etc.), entonces la solución se vuelve un poco más compleja. Este es mi intento.
También agregué algunas opciones para elegir si desea registrar 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 arreglos convertidos.
Lo ideal es que pruebes 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;
}
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 }) );
Solo usa lo siguiente:
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)
Sugiero usar la interfaz 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())
También puede lograr esto mediante el uso de 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);
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(''&'');
}
Un poco se ven 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("&");
}
Una pequeña enmienda a la solución aceptada por el usuario 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("&");
}
La comprobación de hasOwnProperty en el objeto hace feliz a JSLint / JSHint, y evita la serialización accidental de métodos del objeto u otras cosas si el objeto no es más que un simple diccionario. Consulte el párrafo sobre las declaraciones en esta página: http://javascript.crockford.com/code.html
jQuery tiene una función para esto, jQuery.param()
, si ya lo estás usando, puedes 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
ok, es una publicación antigua, pero me enfrento a 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;
};
utilizar JSON.
Eche un vistazo a esta pregunta para obtener ideas sobre cómo implementar.
ES6 SOLUCIÓN PARA CODIFICACIÓN DE CUERDAS DE CODIGO DE UN OBJETO DE 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"
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
Object.keys(obj).reduce(function(a,k){a.push(k+''=''+encodeURIComponent(obj[k]));return a},[]).join(''&'')
Edit: me gusta esta frase, pero apuesto a que sería una respuesta más popular si coincidiera semánticamente con la respuesta aceptada:
function serialize( obj ) {
return ''?''+Object.keys(obj).reduce(function(a,k){a.push(k+''=''+encodeURIComponent(obj[k]));return a},[]).join(''&'')
}