Когда мы используем JS для запроса данных из (реляционной) базы данных, наиболее распространенным способом получения данных является список объектов.
Часто в этих данных повторяются первые значения, например, это дни, отработанные человеком, или покупки, совершенные клиентом.
В моей работе мне часто приходится конвертировать этот список объектов в иерархический объект, т.е. многоуровневый json или другими словами дерево. После некоторого конкретного преобразования я решил потратить некоторое время на создание универсальнойфункции, в которой глубина дерева зависит от количества переданных ключей. к функции.
Поскольку я не думаю, что я единственный, у кого такая необходимость, я решил поделиться этим кодом со всеми вами.
Для функции generateDictFromListOfObj требуются 3 параметра:
- data:список объектов для преобразования
- список levelsKeys: ключей, которые будут использоваться для построения дерева
-valuesKeys: список ключей, которые представляют собой ключи значений для использования в оставить узлы
/** * This method transform a list of object aka rows of a query in a JSON multilevel tree * @param {Array.<Object>} data - the array of object to convert * @param {Array.<String>} levelsKeys - the key to use to buld the tree * @param {Array.<String>} valuesKeys - the key to use on the leaves (the last level of the tree) * @return {Object} - the object build by the function */ function generateDictFromListOfObj_simple(data, levelsKeys, valuesKeys) { let retObj = {}; if (data.length === 0) return retObj; let d= retObj; for (let key of levelsKeys) { d[data[0][key]] = {}; d = d[data[0][key]]; } for (let row of data) { let d= retObj; let lastLevel_d= {}; let key = null; for (key of levelsKeys) { if (!d.hasOwnProperty(row[key])) { d[row[key]] = {}; } lastLevel_d = d; d = d[row[key]]; } let dummy = {}; for (let keyValue of valuesKeys) { dummy[keyValue] = row[keyValue]; } lastLevel_d[row[key]] = dummy; } return retObj; } /** * This method transform a list of object aka rows of a query in a JSON multilevel tree * @param {Array.<Object>} data - the array of object to convert * @param levelsKeys {Array.<Object>} - the list of object to use to idenfied the keys of the tree, every object has 3 keys * @param levelsKeys.key {String} - the key of the level * @param levelsKeys.attributes {Array.<String>} - the list of the attributes of that level * @param levelsKeys.nested {String} - the name of the key to use for the nested level * @return {Object} - the object build by the function */ function generateDictFromListOfObj(data, levelsKeys) { let retObj = {}; if (data.length === 0) return retObj; let d= retObj; let row = data[0]; for (let keyRow of levelsKeys) { d[row[keyRow.key]] = {}; for (let attr of keyRow.attributes) { d[row[keyRow.key]][attr] = row[attr] } d[row[keyRow.key]][keyRow.nested] = {}; d = d[row[keyRow.key]][keyRow.nested]; } for (let row of data) { let d= retObj; let lastLevel_d= {}; let keyRow = null; for (keyRow of levelsKeys) { if (!d.hasOwnProperty(row[keyRow.key])) { d[row[keyRow.key]] = {}; for (let attr of keyRow.attributes) { d[row[keyRow.key]][attr] = row[attr] } d[row[keyRow.key]][keyRow.nested] = {}; } lastLevel_d = d; d = d[row[keyRow.key]][keyRow.nested]; } let dummy = {}; for (let keyValue of keyRow.attributes) { dummy[keyValue] = row[keyValue]; } lastLevel_d[row[keyRow.key]] = dummy; } return retObj; }
Атрибуты, связывающие уровень, определяются в атрибутах, а имя ключа подуровня определяется в вложенном.
И это пример для проверки функции.
let lavorato = [ { dipendente: 'Paolino Paperino', cognome: 'Paperino', nome: 'Paolino', id_commessa: 1286, dataiso: '20230901', qta: 8, commessa: 'ZZZ-000-PLM-VARIE - 3PV246 - - GALEOTTI', colore: '#0088ff', descrizione: '#1286 VARIE - PROVA MAPI ', id_dipendente: 5 }, { dipendente: 'Paperino Paolino', cognome: 'Paperino', nome: 'Paolino', id_commessa: 1286, dataiso: '20230902', qta: 8, commessa: 'ZZZ-000-PLM-VARIE - 3PV246 - - GALEOTTI', colore: '#0088ff', descrizione: '#1286 VARIE - PROVA MAPI ', id_dipendente: 5 } ]; let levelsKeys = [ {key: 'id_dipendente', attributes: ["dipendente", "cognome", "nome"], nested: "commesse"}, {key: 'id_commessa', attributes: ["colore", "commessa"], nested: "giorni"}, {key: 'dataiso', attributes: ['qta', 'descrizione']} ]; let chk = generateDictFromListOfObj(lavorato, levelsKeys); console.log(JSON.stringify(chk, null, 2));
Теперь у меня есть то, что мне нужно, но я буду рад получить предложения по улучшению кода.
Хорошие рабочие друзья.