天天看點

如何使用 JavaScript 扁平化/非扁平化嵌套 JSON 對象?#yyds幹貨盤點#

如何使用 JavaScript 扁平化/非扁平化嵌套 JSON 對象?#yyds幹貨盤點#

前端開發中,特别有接觸過樹形結構元件的項目中,這些元件很多都需要對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

總結

繼續閱讀