#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") ); // поехали
Комментариев нет:
Отправить комментарий