天天看点

如何使用 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

总结

继续阅读