Кодування за допомогою рядка запиту об'єкта Javascript


481

Чи знаєте ви швидкий і простий спосіб кодування об'єкта Javascript у такий, stringякий я можу передати через GETЗапит?

Ні jQuery, ніяких інших рамок - просто звичайний Javascript :)


Чому JQuery не може бути рішенням, якщо для вашого рішення є відповідне?
eaglei22

@ eaglei22, тому що в той час я працював над проектом для пристрою IPTV-приставки, і зовнішні бібліотеки заборонено. ;-)
napolux

1
Дякуємо за відповідь. Я час від часу бачу цю специфікацію і завжди цікавився сценарієм, чому. Ну, тепер я отримав один, дякую! :)
eaglei22

9
@ eaglei22 Тому що іноді не хочеться завантажувати велику бібліотеку, щоб отримати один елемент за ідентифікатором.
Аарон Харун

Більшість браузерів URLSearchParamsзараз підтримують ...
mb21

Відповіді:


810

подобається це?

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


2
Чи не буде перерва дано {foo: [1,2,3], бар: "100%"}?
Квентін

1
@Ofri: Для запитів POST до сервера, налаштованого на його отримання, JSON - хороший вибір. Для GET-запитів, якщо ви надсилаєте на сервер що-небудь, крім кількох простих параметрів, можливо, ваш дизайн неправильний.
Тім Даун

2
@Marcel Це тому, що функція не перевіряє наявність hasOwnProperty. Я оновив вашу загадку,
Rudie

1
@TimDown Щодо коментаря, який надсилає прості параметри в GET-запитах. Я не згоден. Групування параметрів у масиви може стати зручним, оскільки PHP на стороні сервера знаходить готовий стійкий асоціативний масив. Я не бачу, чому це неправильно як дизайн.
Савас Ведова

1
Чи потрібно "if (obj.hasOwnProperty (prop))"? Цикл тверджень for in тільки над властивостями об'єкта, тому виклик hasOwnProperty завжди оцінюється як істинний
Арнон,

231

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


119
Цитуючи Napolux (OP): "просто звичайний Javascript" . : P
Sk8erPeter

6
jQuery.param () має зловісну поведінку. Спробуйте виконати var a = []; a [2564] = 12; console.log (jQuery.param ({propertylist: a})); щоб побачити, що я маю на увазі.
аконд

13
@akond Документація jQuery спеціально говорить про те, що ви не можете пройти в голому масиві.
Аріель

4
@Ariel Він не проходить в голому масиві. Він проходить масив із лише одним значенням в індексі 2564. Для демонстрації: var a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); Результати в "parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo". Що, хоча і правильно, може бути не тим, чого ви очікуєте.
Кріс Холл

4
Питання спеціально задали Vanilla JS
Bug Hunter 219

188

Просто використовуйте URLSearchParamsЦе працює у всіх поточних браузерах

new URLSearchParams(object).toString()

5
Ні, як це не робить рекурсивних об'єктів
Едді Монж, молодший

Не працює над вкладеним об'єктом. let j = { m: 5, n: { k: 1 } }; new URLSearchParams(j).toString(); // result "m=5&n=%5Bobject+Object%5D"
hitautodestruct

19
@EddieMongeJr Рядки запитів - це пара ключових значень за дизайном, ви навіть не хочете серіалізувати вкладені об'єкти. Ця відповідь - це сучасний шлях. Необхідні оновлення.
Ромен Дюран

5
Так, вони є ключовими парами значень, але нічого не говорить про те, що значення не може бути об'єктом, кодованим рядком. Також в оригінальних питаннях задається "Об'єкт Javascript в рядок", який може мати вкладені властивості
Едді Монж, молодший

@EddieMongeJr навіть прийнята відповідь (та інші після короткого огляду) не підтримує вкладений об’єкт. Ви можете stringifyвкласти об’єкти, перш ніж зможетеURLSearchParams
Мош Феу

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

1
Виділений рядок функції зменшення значно покращить читабельність.
Aurelien Ribon

54
Використання .map () замість .reduce () було б ще простіше: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Jannes

2
Зауважимо Object.keysлише, що це доступно лише в IE> = 9
Johnston

5
Далі вдосконалено код @Jannes, використовуючи шаблони ES6 замість конкатенації -Object.keys(obj).map(k => `${k}=${encodeURIComponent(obj[k])}`).join('&')
csilk

1
Якщо ваші ключі потребують кодуванняUriComponent ❤️ теж: Object.entries(obj).map(e => e.map(ee => encodeURIComponent(ee)).join('=')).join('&');
Blaise

112

Ось один вкладиш в ES6:

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

замінити ключ ж / к і ти золотий
Джеймі Кудла

17
Увага! Це працює лише на дрібних об'єктах. Якщо у вас є властивість верхнього рівня, що є іншим об'єктом, цей один вкладиш видасть "key =% 5Bobject% 20Object% 5D". Так само, як голови вгору.
Ендрю Олбрайт

4
Крім того, це не сплюває масиви. Я отримав, export?actions[]=finance,create,editколи це повинно бути export?actions[]=finance&actions[]=create&actions[]=editтаким, як це жахливий стандарт.
darkbluesun

3
Масиви - це завжди завжди "ти сам", тому що аргументи URL - це лише рядки, що стосуються специфікації, тож ти на гачку, щоб зробити все, що не є однією строкою, читається правильно сервером ти дзвониш. actions[]є позначення PHP; Джанго використовує actionнатомість кілька (без []суфікса); деякі інші ORM / CMS потребують списків, розділених комами, і т. д. Отже, "якщо це не прості рядки, спочатку переконайтеся, що ви знаєте, чого навіть хоче ваш сервер".
Майк 'Pomax' Камерманс

Дуже елегантне рішення!
Ань Тран

51

З Node.js v6.6.3

const querystring = require('querystring')

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

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

Довідка: https://nodejs.org/api/querystring.html


8
Це не повинно бути обмеженим IMO, якщо це JS на сервері, це має бути правильною відповіддю.
Майкл Бенін

4
Схоже, він не підтримує вкладені об’єкти.
Ярін Золото

43

Я пропоную використовувати 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();

1
Цікава пропозиція, але майте на увазі, що підтримка браузера для цієї функції все ще дуже нерівна.
mrec

Якщо ви не підтримуєте IE (який зараз досить поширений) та деякі конкретні мобільні версії, це найкраща відповідь, оскільки це звичайний JavaScript.
Маркос

24

Невелика поправка до прийнятого рішення користувачем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


14

Що ж, схоже, кожен поклав сюди свій одноколісний лайнер, так що тут йде моє:

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

1
Object.entries не підтримується в IE.
MBouwman

@MBouwman, звичайно, IE зламаний поза добром і злом, тому вам доведеться використовувати babel / core-js
chpio

@chpio Babel / core-js не підтримує Object.entries, якщо я правий.
MBouwman

ядро має підтримку для Object.entries: github.com/zloirock/core-js/blob/master/…, і навіть стара трансформація бабеля Corejs2 виконує його, а також github.com/babel/babel/blob/…
chpio

12

Чи потрібно надсилати довільні об’єкти? Якщо так, 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() );

11

Рейки / PHP Style Query Builder

Цей метод перетворює об'єкт 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, '') ...
developer033

8

використовувати JSON.

погляньте на це питання, щоб дізнатися, як реалізувати.


2
Я не знаю, в що він пише сервер, але в більшості сучасних мов є гарні пакети, які читають JSON. Крім того, навіть якщо він закінчить його реалізувати, краще реалізувати код зчитування сервера JSON, ніж вигадувати нову власну схему кодування. Кодування "DIY", подібні до цієї, як правило, є баггі (тому що ви зазвичай не замислюєтесь про всі можливі випадки, як, наприклад, значення є масивом саме по собі тощо ").
Офрі Равів

ви в основному пропонуєте перетворити об'єкт у JSON і потім передати весь рядок JSON на сервер як єдиний параметр GET запиту?
Марко Демайо

8

Ось кофесценна версія прийнятої відповіді. Це може заощадити час комусь.

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

Дякую Альфонсо! Дійсно врятував мій час!
Лукас

6

Ось стисла та рекурсивна версія з 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"

Ця версія зробила роботу для мене під час роботи з вкладеними масивами. Нещодавно змінилося використання клавіш масиву у стилі Ruby / PHP, але в іншому випадку це чудово.
нік

5

Це пропускає нульові / невизначені значення

export function urlEncodeQueryParams(data) {
    const params = Object.keys(data).map(key => data[key] ? `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}` : '');
    return params.filter(value => !!value).join('&');
}

5

У ES7 ви можете написати це одним рядком:

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

4

Єдиний рядок для перетворення Об'єкта в рядок запитів, якщо комусь знову потрібен

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

4

У мене є більш просте рішення, яке не використовує жодної сторонньої бібліотеки і вже вдається використовуватись у будь-якому браузері, який має "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('&');
}

3

Якщо ви хочете перетворити вкладений об'єкт рекурсивно і об'єкт може містити або не може містити масиви (а масиви можуть містити об'єкти або масиви тощо), тоді рішення стає трохи складнішим. Це моя спроба.

Я також додав кілька варіантів, щоб вибрати, чи потрібно записувати для кожного члена об'єкта, на якій глибині основного об'єкта він сидить, і вибрати, чи потрібно додати мітку до членів, що надходять із перетворених масивів.

В ідеалі слід перевірити, чи дійсно параметр речі отримує об'єкт або масив.

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;

}

Дякую за рекурсивний підхід
Шерлок

3

Крім прийнятого рішення, це працює з об'єктами та масивом об'єктів:

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.


3

Трохи виглядайте краще

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

3

Я зробив порівняння стринг-фіксаторів 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 .


2

ОК, це старший пост, але я зіткнувся з цією проблемою, і я знайшов своє особисте рішення .. Можливо, я можу допомогти комусь іншому ..

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

2

Наведені вище відповіді заповнювати не спрацьовують, якщо у вас багато вкладених об’єктів. Натомість ви можете обрати парам функцій звідси - 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, '+');
};

2

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"

2

Це рішення, яке буде працювати для програм .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;
}

1

Я написав пакет саме для цього: 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

0

Просто інший спосіб (без рекурсивного об'єкта):

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

0

Зверніться до відповіді @ 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);

0

Ви також можете досягти цього, використовуючи простий 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);


1
Це приємна вправа, але це навпаки. Не відповідь на запитання.
Крістіан Вестербек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.