logo

オブジェクトの平坦化

オブジェクトをフラットにしたり、フラットなオブジェクトを元に戻したりするJS
lodashzipObjectDeep に依存
CakePHPのHash::flatten のようなもの
zipObjectDeep で展開するため、キーの構成は Hash::flatten とは異なる

import _ from 'lodash'; const numberRE = /^(?:0|[1-9][0-9]*)$/; const flatten = (originalData) => { const result = {}; const stack = []; let paths = []; let data = JSON.parse(JSON.stringify(originalData)); while(true) { data = { ...data }; const key = Object.keys(data).shift(); if (key) { const element = data[key]; delete data[key]; if (element !== null && typeof element === 'object' && Object.keys(element).length) { if (data) { stack.push([data, [...paths]]); } data = element; if (numberRE.test(key)) { if (paths.length && paths[paths.length - 1] === '.') { paths.pop(); } paths.push(`[${key}]`); } else { paths.push(key); } paths.push('.'); } else { result[`${paths.join('')}${key}`] = element; } } if (!Object.keys(data).length) { if (stack.length) { [data, paths] = stack.shift(); } else { break; } } } return result; } const expand = (data) => { const keys = []; const values = []; const dataKeys = Object.keys(data); let key = dataKeys.shift(); while(key) { keys.push(`result.${key}`); values.push(data[key]); key = dataKeys.shift(); } const { result } = _.zipObjectDeep(keys, values); return result; }