nodejs将json对象转化为excel表导出的方法

将json数据导出到excel表

应用情景

在同一文件夹下有若干json文件,json文件中包含接口请求和返回报文的数据参数名和参数类型等信息。现需要同一该文件夹下所有json文件中所有的参数名及其出现次数,并将其以excel表格的形式导出作为统计对比。

json数据样式

{
	"Metadata": {
		"ServiceId": "serviceID",
		"InterfaceName": "接口名称",
		"Uri": "http:/example/theUrl",
		"RequestType": "json/wsdl",
		"RequestProtocol": "http",
		"InterfaceDescription": "测试"
	},
	"Request": {
		"$schema": "http://json-scma.org/theurl",
		"type": "object",
		"required": true,
		"properties": {
			"ReqBody": {
				"type": "object",
				"required": true,
				"properties": {
                    "paramA": {
                        "description": "参数1",
                        "type": "string",
                        "required": true
                      },
                     "paramb": {
                        "description": "参数2",
                        "type": "string",
                        "required": false
                      },
                     "name": {
                        "description": "姓名",
                        "type": "string",
                        "required": true
                      },
				}
			}
		}
	},
	"Response": {
		"$schema": "http://json-s/chema",
		"type": "object",
		"required": true,
		"properties": {
			"RspBody": {
				"type": "object",
				"required": true,
				"properties": {
                    "paramA": {
                        "description": "参数1",
                        "type": "string",
                        "required": true
                      },
                     "paramc": {
                        "description": "参数3",
                        "type": "string",
                        "required": false
                      },
                     "Id": {
                        "description": "id",
                        "type": "string",
                        "required": true
                      },
                    "items":{
                        "dessription":"ssds",
                        "type":"array",
                        "properties":{
                          "arrayName":[{
                            "arrayParam":"param",
                            "arrayParam22":"31"
                          }]
                        }
				}
			}
		}
	}
}

实现方法

  1. 首先需要导入所有需要统计的json文件到一个对象数组中,以便后续进行对数据的遍历。
let fs = require('fs') //导入文件读取所需要的fs模块

//以同步的方式获取当前文件夹下所有json文件名,获取所有文件数据并写入newData数组中
let dir = fs.readdirSync("./")
let newData = []
for (const iterator of dir) {
    //获取对应文件名的具体内容,存入newData数组
    let dataElement = require('./' + iterator)
    newData.push(dataElement)
}
  1. 设置input和output对象作为记录所有参数及其出现次数的全局变量
let input ={}, output ={} //初始情况下二者皆为空对象
    • 获取到所有需要的数据就要对其进行处理。已知所有json文件都具有Request和Response部分,将其作为判断是否进行后续分析处理的入口,以此排除掉文件夹中可能出现的不属于json格式的数据。Request和Response部分的数据格式基本相同,因此可以使用类似的方法进行处理。

    • 首先获取其内部实际存储参数名和类型的子对象,即Request.properties.ReqBody.properties部分,若其不是array类型,则其内部没有子对象,是一个string或number类型的普通参数。

    • 那么遍历input对象,比较参数名是否已在input对象中。若input中没有该参数名则添加该参数名,value初值设置为1,若input中已有该参数名这则将其value值在原来的基础上加一。

    • 若其是array类型,说明仍有子对象,需要进一步遍历。尤其数据格式可知子对象在value.items.properties中,对其进行上述类似处理即可

    • 对于Response对象的处理与Request的处理类似

//记录参数名及其出现次数方法
function getParam(data) {

    if (data.Request && data.Response) {
        let req = data.Request.properties.ReqBody.properties    //请求报文参数
        let res = data.Response.properties.RspBody.properties   //响应报文参数

        for (const [key, value] of Object.entries(req)) {
            //若type不是array则不是数组类型,无嵌套,对应的值存入对象即可
            if (value.type !== 'array') {
                let flag = false    //flag为false则input中没有对应的值

                //查找当前input中是否有该报文中的参数,若有,则值+1,否则将设置其出现的次数初值为1
                for (const [key1, value1] of Object.entries(input)) {
                    if (key1 === key) {
                        flag = true
                        break
                    }
                }
                if (flag) {
                    input[key] = input[key] + 1
                } else {
                    input[key] = 1
                }
            } else {
                //type为array类型,有数组嵌套数据,需要进一步的获取到value.items.properties进行遍历,原理同上
                for (const [key1, value1] of Object.entries(value.items.properties)) {
                    for (const [key2, value2] of Object.entries(input)) {
                        if (key2 === key1) {
                            flag = true
                            break
                        }
                    }
                    if (flag) {
                        input[key1] = input[key1] + 1
                    } else {
                        input[key1] = 1
                    }
                }
            }
        }
        // console.log(input);

        //获取响应报文参数出现次数,原理同上
        for (const [key, value] of Object.entries(res)) {
            let flag = false    //flag为false则input中没有对应的值

            if (value.type !== 'array') {
                for (const [key1, value1] of Object.entries(output)) {
                    if (key1 === key) {
                        flag = true
                        break
                    }
                }
                if (flag) {
                    output[key] = output[key] + 1
                } else {
                    output[key] = 1
                }
            } else {
                for (const [key1, value1] of Object.entries(value.items.properties)) {
                    for (const [key2, value2] of Object.entries(output)) {
                        if (key2 === key1) {
                            flag = true
                            break
                        }
                    }

                    if (flag) {
                        output[key1] = output[key1] + 1
                    } else {
                        output[key1] = 1
                    }
                }
            }
        }
        // console.log(output);
    }
}
  1. 将数据导出到excel文件中
let XLSX = require('js-xlsx')

//导出excel
function geneExcel(input1, output1) {
    /** newJson数据格式:
     *  [{paramA:1},{paramB:2}...]
     */
    let newJson = []
    for (const [key, value] of Object.entries(output1)) {
        newJson.push({ paramName: key, value: value })
    }


    let tmpdata = newJson[0];
    newJson.unshift({});
    let keyMap = []; //获取keys
    //keyMap =Object.keys(json[0]);
    for (let k in tmpdata) {
        keyMap.push(k);
        newJson[0][k] = k;
    }
    let tmpdata = [];//用来保存转换好的json 
    newJson.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
        v: v[k],
        position: (String.fromCharCode(65 + j)) + (i + 1)
    }))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {
        v: v.v
    });
    let outputPos = Object.keys(tmpdata); //设置区域,比如表格从A1到D10
    console.log(tmpdata);



    /**
     * workboot标准写法
     * {
     *  SheetName:['SheetName'],
     *  Sheets:{
     *      'SheetName':{
     *          '!ref':'A1:E4', //必须要有这个范围才能输出,否则导出的 excel 会是一个空表
     *          A1:{v:'id'},
     *          A2:{v:'name'},
     *      }
     *  }
     * }
     */
    let tmpWB = {
        SheetNames: ['mySheet'], //保存的表标题
        Sheets: {
            'mySheet': Object.assign({},
                tmpdata, //内容
                {
                    '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] //设置填充区域
                })
        }
    };
    //导出excel
    XLSX.writeFile(tmpWB, 'output.xlsx');



}
  1. 所有代码整合示例
let XLSX = require('js-xlsx')
let fs = require('fs')

//全局定义输入和输出字段名称和出现次数{key:paramName,value:actTime}
let input = {}
let output = {}

//读入当前文件夹下所有json文件,将所有文件数据写入newData数组中
let dir = fs.readdirSync("./")
let newData = []
for (const iterator of dir) {
    //获取对应文件名的具体内容,存入newData数组
    let dataElement = require('./' + iterator)
    newData.push(dataElement)
}

//遍历数组内容,获取参数名称并记录出现次数
for (let i = 1; i < newData.length; i++) {
    getParam(newData[i])
}
// console.log(input);
// console.log(output);

//得到参数数据结果,导出为excel文件
geneExcel(input, output)

//记录参数名及其出现次数方法
function getParam(data) {

    if (data.Request && data.Response) {
        let req = data.Request.properties.ReqBody.properties    //请求报文参数
        let res = data.Response.properties.RspBody.properties   //响应报文参数

        for (const [key, value] of Object.entries(req)) {
            //若type不是array则不是数组类型,无嵌套,对应的值存入对象即可
            if (value.type !== 'array') {
                let flag = false    //flag为false则input中没有对应的值

                //查找当前input中是否有该报文中的参数,若有,则值+1,否则将设置其出现的次数初值为1
                for (const [key1, value1] of Object.entries(input)) {
                    if (key1 === key) {
                        flag = true
                        break
                    }
                }
                if (flag) {
                    input[key] = input[key] + 1
                } else {
                    input[key] = 1
                }
            } else {
                //type为array类型,有数组嵌套数据,需要进一步的获取到value.items.properties进行遍历,原理同上
                for (const [key1, value1] of Object.entries(value.items.properties)) {
                    for (const [key2, value2] of Object.entries(input)) {
                        if (key2 === key1) {
                            flag = true
                            break
                        }
                    }
                    if (flag) {
                        input[key1] = input[key1] + 1
                    } else {
                        input[key1] = 1
                    }
                }
            }
        }
        // console.log(input);

        //获取响应报文参数出现次数,原理同上
        for (const [key, value] of Object.entries(res)) {
            let flag = false    //flag为false则input中没有对应的值

            if (value.type !== 'array') {
                for (const [key1, value1] of Object.entries(output)) {
                    if (key1 === key) {
                        flag = true
                        break
                    }
                }
                if (flag) {
                    output[key] = output[key] + 1
                } else {
                    output[key] = 1
                }
            } else {
                for (const [key1, value1] of Object.entries(value.items.properties)) {
                    for (const [key2, value2] of Object.entries(output)) {
                        if (key2 === key1) {
                            flag = true
                            break
                        }
                    }

                    if (flag) {
                        output[key1] = output[key1] + 1
                    } else {
                        output[key1] = 1
                    }
                }
            }
        }
        // console.log(output);
    }
}


//导出excel
function geneExcel(input1, output1) {
    /** newJson数据格式:
     *  [{paramA:1},{paramB:2}...]
     */
    let newJson = []
    for (const [key, value] of Object.entries(output1)) {
        newJson.push({ paramName: key, value: value })
    }


    let tmpdata = newJson[0];
    newJson.unshift({});
    let keyMap = []; //获取keys
    //keyMap =Object.keys(json[0]);
    for (let k in tmpdata) {
        keyMap.push(k);
        newJson[0][k] = k;
    }
    let tmpdata = [];//用来保存转换好的json 
    newJson.map((v, i) => keyMap.map((k, j) => Object.assign({}, {
        v: v[k],
        position: (String.fromCharCode(65 + j)) + (i + 1)
    }))).reduce((prev, next) => prev.concat(next)).forEach((v, i) => tmpdata[v.position] = {
        v: v.v
    });
    let outputPos = Object.keys(tmpdata); //设置区域,比如表格从A1到D10
    console.log(tmpdata);



    /**
     * workboot标准写法
     * {
     *  SheetName:['SheetName'],
     *  Sheets:{
     *      'SheetName':{
     *          '!ref':'A1:E4', //必须要有这个范围才能输出,否则导出的 excel 会是一个空表
     *          A1:{v:'id'},
     *          A2:{v:'name'},
     *      }
     *  }
     * }
     */
    let tmpWB = {
        SheetNames: ['mySheet'], //保存的表标题
        Sheets: {
            'mySheet': Object.assign({},
                tmpdata, //内容
                {
                    '!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1] //设置填充区域
                })
        }
    };
    //导出excel
    XLSX.writeFile(tmpWB, 'output.xlsx');



}

效果

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值