オブジェクトをフラットにしたり、フラットなオブジェクトを元に戻したりするJS
lodash の zipObjectDeep
に依存
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;
}