![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsAjMfd3bkFGazxCMx8VesATMfhHLlN3XnxCMz8FdsYkRGZkRG9lcvx2bjxSa2EWNhJTW1AlUxEFeVRUUfRHelRHL0EzXlpXazxyayFWbyVGdhd3LcV2Zh1Wa9M3clN2byBXLzN3btg3PnVGcq5SN0EDM4MDN0MDN1kDOzYTMvwFOwITMxIDMy8CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.jpeg)
前端開發中,特别有接觸過樹形結構元件的項目中,這些元件很多都需要對JSON對象進行扁平化,而擷取屬性資料又需要對資料進行反操作。本文以代碼的形式來展示如何使用 JavaScript 扁平化/非扁平化嵌套的 JSON 對象。
概念
先來看下 JSON 扁平化和非扁平化是什麼,請看下面的代碼:
扁平化 JSON
{
"articles[0].comments[0]": "comment 1",
"articles[0].comments[1]": "comment 2",
}
非扁平化 JSON
非扁平化,即常見的 JSON 對象,如下:
{
"articles": [
{
"comments": [
"comment 1",
"comment 2"
]
}
]
}
扁平化
将非扁平化 JSON 資料轉為扁平化的,這裡定義了函數
flatten
,如下:
const flatten = (data) => {
const result = {};
const isEmpty = (x) => Object.keys(x).length === 0;
const recurse = (cur, prop) => {
if (Object(cur) !== cur) {
result[prop] = cur;
} else if (Array.isArray(cur)) {
const length = cur.length;
for (let i = 0; i < length; i++) {
recurse(cur[i], `${prop}[${i}]`);
}
if (length === 0) {
result[prop] = [];
}
} else {
if (!isEmpty(cur)) {
Object.keys(cur).forEach((key) =>
recurse(cur[key], prop ? `${prop}.${key}` : key)
);
} else {
result[prop] = {};
}
}
};
recurse(data, "");
return result;
};
const obj = {
"articles": [
{
"comments": [
"comment 1",
"comment 2"
]
}
]
};
console.log(flatten(obj));
/*
{
'articles[0].comments[0]': 'comment 1',
'articles[0].comments[1]': 'comment 2'
}
*/
上面的代碼在函數中定義了一個遞歸函數
recurse
。
非扁平化
将扁平化的JSON 資料轉換為非扁平化的,為了解壓一個扁平化的 JavaScript 對象,需要拆分每個屬性路徑并将嵌套的屬性添加到解壓對象中。
const unflatten = (data) => {
if (Object(data) !== data || Array.isArray(data)) {
return data;
}
const regex = /\.?([^.\[\]]+)$|\[(\d+)\]$/;
const props = Object.keys(data);
let result, p;
while ((p = props.shift())) {
const match = regex.exec(p);
let target;
if (match.index) {
const rest = p.slice(0, match.index);
if (!(rest in data)) {
data[rest] = match[2] ? [] : {};
props.push(rest);
}
target = data[rest];
} else {
if (!result) {
result = match[2] ? [] : {};
}
target = result;
}
target[match[2] || match[1]] = data[p];
}
return result;
};
const result = unflatten({
"articles[0].comments[0]": "comment 1",
"articles[0].comments[1]": "comment 2",
});
console.log(JSON.stringify(result, null, "\t"));
/*
{
"articles": [
{
"comments": [
"comment 1",
"comment 2"
]
}
]
}
*/
上面代碼建立
unflatten
函數來處理一個扁平的對象,函數參數為
data
,可以是任何值,包括
Object
、
Array
、
String
、
Number
等等。在函數中,先判斷參數
data
是否為對象、數組,如果為對象、數組,則直接傳回
data
。反之,使用正規表達式來解析屬性的結構。
props
為參數
data
的屬性,然後周遊鍵并調用
regex.exec
以擷取屬性路徑部分并将其指派給變量
match
。接下來,擷取提取的屬性部分的索引
index
。