Чи знаєте ви швидкий і простий спосіб кодування об'єкта Javascript у такий, string
який я можу передати через GET
Запит?
Ні jQuery
, ніяких інших рамок - просто звичайний Javascript :)
URLSearchParams
зараз підтримують ...
Чи знаєте ви швидкий і простий спосіб кодування об'єкта Javascript у такий, string
який я можу передати через GET
Запит?
Ні jQuery
, ніяких інших рамок - просто звичайний Javascript :)
URLSearchParams
зараз підтримують ...
Відповіді:
подобається це?
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
Редагувати: цей також перетворює рекурсивні об'єкти (використовуючи позначення php "масив" для рядка запиту)
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
var a = []; a[5] = 'foo'; jQuery.param({ parameters: a });
Результати в "parameters[]=¶meters[]=¶meters[]=¶meters[]=¶meters[]=¶meters[]=foo"
. Що, хоча і правильно, може бути не тим, чого ви очікуєте.
Просто використовуйте URLSearchParams
Це працює у всіх поточних браузерах
new URLSearchParams(object).toString()
let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
stringify
вкласти об’єкти, перш ніж зможетеURLSearchParams
Object.keys(obj).reduce(function(a,k){a.push(k+'='+encodeURIComponent(obj[k]));return a},[]).join('&')
Редагувати: Мені подобається ця однолінійка, але я вважаю, що це була б більш популярна відповідь, якби вона семантично відповідала прийнятій відповіді:
function serialize( obj ) {
let str = '?' + Object.keys(obj).reduce(function(a, k){
a.push(k + '=' + encodeURIComponent(obj[k]));
return a;
}, []).join('&');
return str;
}
Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Object.keys
лише, що це доступно лише в IE> = 9
Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Ось один вкладиш в ES6:
Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
export?actions[]=finance,create,edit
коли це повинно бути export?actions[]=finance&actions[]=create&actions[]=edit
таким, як це жахливий стандарт.
actions[]
є позначення PHP; Джанго використовує action
натомість кілька (без []
суфікса); деякі інші ORM / CMS потребують списків, розділених комами, і т. д. Отже, "якщо це не прості рядки, спочатку переконайтеся, що ви знаєте, чого навіть хоче ваш сервер".
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())
Або передавши об’єкт пошуку в конструктор так:
const obj = {foo: "hi there", bar: "100%" };
const params = new URLSearchParams(obj).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
Що ж, схоже, кожен поклав сюди свій одноколісний лайнер, так що тут йде моє:
const encoded = Object.entries(obj).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join("&");
Чи потрібно надсилати довільні об’єкти? Якщо так, 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() );
Цей метод перетворює об'єкт Javascript в a 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
function
щоб виключити falsy
значення (null, undefined, NaN, '') ...
використовувати JSON.
погляньте на це питання, щоб дізнатися, як реалізувати.
Ось кофесценна версія прийнятої відповіді. Це може заощадити час комусь.
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("&")
Ось стисла та рекурсивна версія з Object.entries . Він обробляє довільно вкладені масиви, але не вкладені об'єкти. Він також видаляє порожні елементи:
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('&'))
Єдиний рядок для перетворення Об'єкта в рядок запитів, якщо комусь знову потрібен
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
У мене є більш просте рішення, яке не використовує жодної сторонньої бібліотеки і вже вдається використовуватись у будь-якому браузері, який має "Object.keys" (так само, як усі сучасні браузери + edge + тобто):
В 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('&');
}
Якщо ви хочете перетворити вкладений об'єкт рекурсивно і об'єкт може містити або не може містити масиви (а масиви можуть містити об'єкти або масиви тощо), тоді рішення стає трохи складнішим. Це моя спроба.
Я також додав кілька варіантів, щоб вибрати, чи потрібно записувати для кожного члена об'єкта, на якій глибині основного об'єкта він сидить, і вибрати, чи потрібно додати мітку до членів, що надходять із перетворених масивів.
В ідеалі слід перевірити, чи дійсно параметр речі отримує об'єкт або масив.
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;
}
Крім прийнятого рішення, це працює з об'єктами та масивом об'єктів:
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("&");
}
Я зробив порівняння стринг-фіксаторів JSON і результати такі:
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
Найкоротший серед них - нотація об’єктів URL .
ОК, це старший пост, але я зіткнувся з цією проблемою, і я знайшов своє особисте рішення .. Можливо, я можу допомогти комусь іншому ..
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;
};
Наведені вище відповіді заповнювати не спрацьовують, якщо у вас багато вкладених об’єктів. Натомість ви можете обрати парам функцій звідси - 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, '+');
};
ES6 РІШЕННЯ ДЛЯ ЯКОГО СТРУКТУРНОГО РЕГУЛЮВАННЯ ОБ'ЄКТУ 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 (парами)
"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"
Це рішення, яке буде працювати для програм .NET backends з коробки. Я взяв основну відповідь цього потоку та оновив його, щоб відповідати нашим потребам .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;
}
Я написав пакет саме для цього: object-query-string :)
Підтримує вкладені об’єкти, масиви, спеціальні функції кодування тощо. Легкий та безкоштовний 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'
});
повертає
filter[brands][]=Audi&filter[models][]=A4&filter[models][]=A6&filter[models][]=A8&filter[accidentFree]=true&sort=milage
Просто інший спосіб (без рекурсивного об'єкта):
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);
Ви також можете досягти цього, використовуючи простий 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);