Запрос-строку кодировки JavaScript-объекта
знаете ли вы быстрый и простой способ кодирования объекта Javascript в string
что я могу пройти через GET
запрос?
нет jQuery
, никаких других фреймворков - просто Javascript:)
28 ответов:
как это?
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: этот также преобразует рекурсивные объекты (используя нотацию php "array" для строки запроса)
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
jQuery имеет функцию для этого,
jQuery.param()
, Если вы уже используете его, вы можете использовать это: http://api.jquery.com/jquery.param/пример:
var params = { width:1680, height:1050 }; var str = jQuery.param( params );
str
теперьwidth=1680&height=1050
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
Edit: мне нравится этот однострочный, но я уверен, что это был бы более популярный ответ, если бы он соответствовал принятому ответу семантически:
function serialize( obj ) { return '?'+Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&') }
вот один лайнер в ES6:
Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
С Узла.Яш В6.6.3
const querystring = require('querystring') const obj = { foo: 'bar', baz: 'tor' } let result = querystring.stringify(obj) // foo=bar&baz=tor
Я предлагаю использовать 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())
небольшая поправка к принятому решению от пользователя 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("&"); }
проверка hasOwnProperty на объекте делает JSLint / JSHint счастливым, и это предотвращает случайную сериализацию методов объекта или других вещей, если объект не является простым словарем. См. параграф на для заявлений на этой странице:http://javascript.crockford.com/code.html
вам нужно отправить произвольные объекты? Если это так, GET-плохая идея, поскольку существуют ограничения на длину URL-адресов, которые будут принимать агенты пользователей и веб-серверы. Мое предложение состояло бы в том, чтобы создать массив пар имя-значение для отправки, а затем создать строку запроса:
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() );
использовать JSON.
посмотри этот вопрос для идей о том, как реализовать.
вот версия CoffeeScript принятого ответа. Это может сэкономить кому-то время.
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("&")
Rails / PHP Style Query Builder
этот метод преобразует объект Javascript в
URI Query String
. Также обрабатывает вложенные массивы и объекты (в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('&'); }
Пример Использования:
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
вот краткая и рекурсивная версия с "объект".записи. Он обрабатывает произвольно вложенные массивы, но не вложенные объекты. Он также удаляет пустые элементы:
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('&'); }
например:
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"
в ES7 вы можете написать это в одну строку:
const serialize = (obj) => (Object.entries(obj).map(i => [i[0], encodeURIComponent(i[1])].join('=')).join('&'))
Ну, каждый, кажется, положил свой один лайнер здесь так вот он идет мой:
const encoded = Object.entries(obj).map(([k, v]) => `${k}=${v}`).join("&");
Если вы хотите преобразовать вложенный объект рекурсивно и объект может или не может содержать массивы (или массивы могут содержать объекты или массивы и т. д.), то решение становится немного более сложным. Это моя попытка.
Я также добавил некоторые опции, чтобы выбрать, хотите ли вы записать для каждого элемента объекта, на какой глубине в основном объекте он находится, и выбрать, хотите ли вы добавить метку к членам, которые поступают из преобразованных массивов.
в идеале, вы должны проверить если параметр действительно получает объект или массив.
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; }
ок, это старый пост, но я столкнулся с этой проблемой и я нашел мое личное решение.. возможно, может помочь кому-то еще..
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; };
дополнение для принятого решения, это работает с объектами & массив объектов:
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("&"); }
также добавили objName, если вы используете параметры объекта, как в asp.net методы действия mvc.
немного лучше выглядеть
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("&"); }
этот пропускает нулевые / неопределенные значения
export function urlEncodeQueryParams(data) { const params = Object.keys(data).map(key => data[key] ? `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}` : ''); return params.filter(value => !!value).join('&'); }
одна строка для преобразования объекта в строку запроса в случае, если кому-то это нужно снова
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
у меня есть более простое решение, которое не использует стороннюю библиотеку и уже может использоваться в любом браузере, который имеет "объект.ключи " (он же все современные браузеры + edge + ie):
в ES5
function(a){ if( typeof(a) !== 'object' ) return ''; return `?${Object.keys(a).map(k=>`${k}=${a[k]}`).join('&')}`; }
в ES3
function(a){ if( typeof(a) !== 'object' ) return ''; return '?' + Object.keys(a).map(function(k){ return k + '=' + a[k] }).join('&'); }
выше ответы заполнить не работает, если у вас есть много вложенных объектов. Вместо этого вы можете выбрать функцию param отсюда -https://github.com/knowledgecode/jquery-param/blob/master/jquery-param.js Это сработало очень хорошо для меня!
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, '+'); };
Я сравнение JSON-стрингификаторов и результаты таковы:
JSON: {"_id":"5973782bdb9a930533b05cb2","isActive":true,"balance":",446.35","age":32,"name":"Logan Keller","email":"logankeller@artiq.com","phone":"+1 (952) 533-2258","friends":[{"id":0,"name":"Colon Salazar"},{"id":1,"name":"French Mcneil"},{"id":2,"name":"Carol Martin"}],"favoriteFruit":"banana"} Rison: (_id:'5973782bdb9a930533b05cb2',age:32,balance:',446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258') O-Rison: _id:'5973782bdb9a930533b05cb2',age:32,balance:',446.35',email:'logankeller@artiq.com',favoriteFruit:banana,friends:!((id:0,name:'Colon Salazar'),(id:1,name:'French Mcneil'),(id:2,name:'Carol Martin')),isActive:!t,name:'Logan Keller',phone:'+1 (952) 533-2258' JSURL: ~(_id~'5973782bdb9a930533b05cb2~isActive~true~balance~'!1*2c446.35~age~32~name~'Logan*20Keller~email~'logankeller*40artiq.com~phone~'*2b1*20*28952*29*20533-2258~friends~(~(id~0~name~'Colon*20Salazar)~(id~1~name~'French*20Mcneil)~(id~2~name~'Carol*20Martin))~favoriteFruit~'banana) QS: _id=5973782bdb9a930533b05cb2&isActive=true&balance=,446.35&age=32&name=Logan Keller&email=logankeller@artiq.com&phone=+1 (952) 533-2258&friends[0][id]=0&friends[0][name]=Colon Salazar&friends[1][id]=1&friends[1][name]=French Mcneil&friends[2][id]=2&friends[2][name]=Carol Martin&favoriteFruit=banana URLON: $_id=5973782bdb9a930533b05cb2&isActive:true&balance=,446.35&age:32&name=Logan%20Keller&email=logankeller@artiq.com&phone=+1%20(952)%20533-2258&friends@$id:0&name=Colon%20Salazar;&$id:1&name=French%20Mcneil;&$id:2&name=Carol%20Martin;;&favoriteFruit=banana QS-JSON: isActive=true&balance=%241%2C446.35&age=32&name=Logan+Keller&email=logankeller%40artiq.com&phone=%2B1+(952)+533-2258&friends(0).id=0&friends(0).name=Colon+Salazar&friends(1).id=1&friends(1).name=French+Mcneil&friends(2).id=2&friends(2).name=Carol+Martin&favoriteFruit=banana
самый короткий среди них обозначение объекта URL.
просто используйте следующее: 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)
просто другой способ (без рекурсивного объекта):
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 }) );
обратитесь к ответу @user187291, добавьте" isArray " в качестве параметра, чтобы преобразовать вложенный массив json.
data : { staffId : "00000001", Detail : [ { "identityId" : "123456" }, { "identityId" : "654321" } ], }
чтобы сделать результат :
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);
вы также можете достичь этого с помощью simple JavaScript.
const stringData = '?name=Nikhil&surname=Mahirrao&age=30'; const newData= {}; stringData.replace('?', '').split('&').map((value) => { const temp = value.split('='); newData[temp[0]] = temp[1]; }); console.log('stringData: '+stringData); console.log('newData: '); console.log(newData);