Кодировка строки запроса объекта Javascript


482

Знаете ли вы быстрый и простой способ кодирования объекта Javascript в объект, stringкоторый я могу передать с помощью GETзапроса?

Нет jQuery, никаких других фреймворков - просто обычный Javascript :)


Почему JQuery не может быть решением, если есть подходящее для вашего решения?
eaglei22

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

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], bar: "100%"}?
Квентин

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

2
@Marcel Это потому, что функция не проверяет hasOwnProperty. Я обновил вашу скрипку, поэтому теперь она работает: jsfiddle.net/rudiedirkx/U5Tyb/1
Rudie

1
@TimDown Относительно вашего комментария отправка простых параметров в запросах GET. Я не согласен. Группирование параметров в массивы может оказаться полезным, так как PHP на стороне сервера находит готовый устойчивый ассоциативный массив. Я не понимаю, почему это неправильно, как дизайн.
Савас Ведова

1
Требуется ли if (obj.hasOwnProperty (prop))? Цикл оператора in только над свойствами объекта, поэтому вызов hasOwnProperty всегда оценивается как true
Арнон,

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
цитируя Наполукса (ОП): «просто обычный Javascript» . : P
Sk8erPeter

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

13
@akond В документации jQuery определенно сказано, что вы не можете передать пустой массив.
Ариэль

4
@ Ариэль Он не проходит мимо Он передает в массиве только одно значение с индексом 2564. Для демонстрации: var a = []; a[5] = 'foo'; jQuery.param({ parameters: a }); Результаты в "parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=&parameters[]=foo". Что, хотя и правильно, может не соответствовать вашим ожиданиям.
Крис Холл,

4
Вопрос специально задал Vanilla JS
Bug Hunter 219

193

Просто используйте 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

20
@EddieMongeJr Строки запроса - это пары ключ-значение по дизайну, вам даже не нужно сериализовать вложенные объекты. Этот ответ - современный путь. Необходимы голоса.
Ромен Дюран

5
Да, они являются парами ключ-значение, но ничто не говорит о том, что значение не может быть объектом со строковым кодированием. Кроме того, в исходных вопросах запрашивается «Объект Javascript в строку», который может иметь вложенные свойства
Эдди Монж-младший

@EddieMongeJr даже принятый ответ (и другие после краткого просмотра) не поддерживает вложенный объект. Вы можете stringifyиспользовать вложенные объекты, прежде чем сможетеURLSearchParams
Mosh Feu

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
Тем не менее, выделенная строка для функции приведения значительно улучшит читабельность.
Аурелиен Рибон

54
Использование .map () вместо .reduce () было бы еще проще: Object.keys(obj).map(k => k + '=' + encodeURIComponent(obj[k])).join('&')
Янв

2
Просто чтобы отметить, что Object.keysдоступно только в IE> = 9
Джонстон

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Вместо этого Django использует множественное число (без []суффикса); некоторым другим 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
Кажется, что он не поддерживает вложенные объекты.
Ярин Голд

45

Я предлагаю использовать 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

@Moubouman, конечно, IE разбит за пределы добра и зла, поэтому вы должны использовать babel / core-js
chpio

@chpio Babel / core-js не поддерживает Object.entries, если я прав.
MBouwman

В ядре есть поддержка Object.entries: github.com/zloirock/core-js/blob/master/… и даже старое преобразование во время выполнения babel в 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

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

Хороший пример. Я исправил опечатку в вашем ответе. Кстати, было бы интересно, если вы измените свой, functionчтобы исключить falsyзначения (null, undefined, NaN, '') ...
developer033

8

используйте JSON.

взгляните на этот вопрос, чтобы узнать, как его реализовать.


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

Вы в основном предлагаете преобразовать объект в JSON, а затем передать всю строку JSON на сервер в виде одного параметра запроса GET?
Марко Демайо

8

Вот версия принятого ответа 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("&")

Спасибо Альфонсо! Действительно сэкономил мое время!
Лукас

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, но в остальном работает отлично.
Nickb

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

3

Если вы хотите преобразовать вложенный объект рекурсивно, и этот объект может содержать или не содержать массивы (а массивы могут содержать объекты или массивы и т. Д.), Решение становится немного более сложным. Это моя попытка.

Я также добавил несколько опций, чтобы выбрать, хотите ли вы записать для каждого элемента объекта, на какой глубине в главном объекте он находится, и выбрать, хотите ли вы добавить метку к элементам, которые поступают из преобразованных массивов.

В идеале вы должны проверить, действительно ли параметр thing получает объект или массив.

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

2

Это решение, которое будет работать для бэкэндов .NET из коробки. Я взял основной ответ этой темы и обновил его, чтобы он соответствовал нашим потребностям .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 & Деталь [0] .identityId = 123456 & Деталь [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.