Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

Конвертация многомерного массива / объекта в формат x-www-form-urlencoded

#javascript #массивы


Необходимо

Конвертировать массив вида:

[
    {
        a: 1,
        b: [1, 2, 3]
    },
    [
        {
            c: 4,
            d: 5,
            e: [
                6,
                {
                    f:7
                }
            ]
        }
    ],
    8
];


в объект вида:

{
    "name[0][a]": 1,

    "name[0][b][0]": 1,
    "name[0][b][1]": 2,
    "name[0][b][2]": 3,

    "name[1][0][c]": 4,
    "name[1][0][d]": 5,

    "name[1][0][e][0][0]": 6,
    "name[1][0][e][0][1][f]": 7,

    "name[2]": 8,
}


name тут чисто для красоты, и может быть использован как один из аргументов на вход
для функции-парсера.

Что пробовал


Гуглить;
Решить рекурсивно (прокомментировал все строки, ибо страшно):




let processObj = (item, key) => { // наша функция-парсер
  if (item.constructor && item.constructor.name === "Array") { // если массив
    item.forEach((item0, key0) => { //перебираем как массив
      processObj(item0, key0); // обратно вызываем processObj, чтобы "докопться"
до обычного значения типа строки или числа
    });
  } else if (item.constructor && item.constructor.name === "Object") { // если объект
    for (let key0 in item) { //перебираем как объект
      processObj(item[key0], key0); // обратно вызываем processObj, чтобы "докопться"
до обычного значения типа строки или числа
    }
  } else { // проверки выше не прошли, а значит это число или строка (скорей всего)
    console.log("key", key, "item", item); // просто смотрим, что к нам пришло в
аргументах
    return {
      [`[${key}]`]: item
    }; // вот тут и начинаются проблемы. Что сюда нужно писать?
  }
}


let arr = [{"a":1,"b":[1,2,3]},[{"c":4,"d":5,"e":[6,{"f":7}]}],8]; // наш массив 'до'
processObj(arr); // должно вернуть желаемый объект




И этот код выглядит логично и успешно проходится по всем элементам и подэлементам
достигая конечного ключа и значения (выполнить, для ясности).

Вопросы


Как заставить этот код откладывать "путь" до найденных чисел или строк, чтобы получить
желаемого вида объект?
Изобретаю ли я велосипед? Есть ли в арсенале js что-нибудь готовое для парсинга массивов
для запроса с данными типа x-www-form-urlencoded?


PS: вариант с JSON.parse() не интересен
    


Ответы

Ответ 1



let arr = [{"a":1,"b":[1,2,3]},[{"c":4,"d":5,"e":[6,{"f":7}]}],8]; const getType = q => Object.prototype.toString.call(q) let res = foo(arr) document.body.innerHTML += `
\n${JSON.stringify(res)} ` function foo(list, props) { let { _path = "", res = {} } = props || {} for (let key in list) { let path = `${_path}['${key}']` let val = list[key] let typeVal = getType(val) if (("[object Array]" === typeVal) || ("[object Object]" === typeVal)) { foo(val, { _path: path, res }) } else { let originVal = eval(`arr${path}`) let isEq = val === originVal document.body.innerHTML += `${JSON.stringify({ path, val, isEq, originVal })}
\n` res[path] = val } } return res }

Ответ 2



Разобрался сам. Комментировать каждую строчку лень поэтому, если возникнут вопросы - задавайте в комментариях - отвечу. Также буду рад кодревью или критике от более опытных js-программистов. Функция записывается в прототип массива и вызвать ее можно так: yourArray.parseForRequest([name]), где name - необязательная строка, которая будет лежать в основании имен свойств полученного объекта. Актуальность / Новизна Посредством этого кода можно отправить многомерный массив на сервер через x-www-form-urlencoded и переменная $_POST примет подмассивы (если они являются массивами) как массивы, а не как [object Object]. Т.е. подмассивы будут доступны как обычно через $_POST[a][b][c][d] - понятно. Array.prototype.parseForRequest = function(name) { let parse = (function() { let pathStore = {}; let parser = (item, key, tempPath) => { (() => { !tempPath && (tempPath = ""); if (item.constructor && item.constructor.name === "Array") { item.forEach((item0, key0) => { let currentPath = tempPath + `[${key0}]`; parser(item0, key0, currentPath); }); } else if (item.constructor && item.constructor.name === "Object") { for (let key0 in item) { let currentPath = tempPath + `[${key0}]`; parser(item[key0], key0, currentPath); } } else { pathStore[tempPath] = item; } })(); return pathStore; } return parser; })(); return parse(this, null, name); } let arr = [{"a":1,"b":[1,2,3]},[{"c":4,"d":5,"e":[6,{"f":7}]}],8]; console.log( arr.parseForRequest("name") ); // поехали

Комментариев нет:

Отправить комментарий