定制小程序开发Java实现将JSON文件导出到Excel

文章目录

一、运行环境


  • windows10
  • IDEA 2022
  • JDK 8
  • Maven 3.8.6
  • Apache POI 5
  • fastjson2

二、需求描述


定制小程序开发写一个功能,任意json生成excel,定制小程序开发每个数组都单独生成一个sheet。

三、实现思路


参考资料:

定制小程序开发主要实现思路: 使用支持Java对象与、定制小程序开发字符串互相转换的fastjson,以及支持Java将JSON转化Excel的库 apache-poi

Excel定制小程序开发表格关键结构:

  • Workbook 工作台,定制小程序开发相当于一个 excel文件
  • sheet,一个excel定制小程序开发文件中的表格页面,定制小程序开发可能有多个
    • row,所在sheet中的行
      • cel,所在sheet定制小程序开发中所在行的列
        • value,定制小程序开发所在单元格的值

JSON转换的几种情形与实现思路:

情形一:普通的单层结构,多个JSON对象

{    "班级A" : [{      "文章":"课文1",      "作者":"李白"    },    {      "文章":"课文2",      "作者":"小李"    },    {      "文章":"课文2",      "作者": "小明"    }]}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

导出结果:


当我们使用遍历JSONObject时,每次读取到的都是单个{ } 所包含的对象,比如:

{  "文章":"课文1",  "作者":"李白"}
  • 1
  • 2
  • 3
  • 4

这种情况下,我们在Excel的Sheet中的行是确定的,比如这里就是第二行(第一行是列名),行根据遍历的顺序确定,而列则是不确定的,在这里有 “文章”,“作者” 这两个列,但是一开始这两个列是不存在的。这里则确定文章在第一列,作者按第二列(默认升序排序)。

当遍历下一个对象时,我们可能遇到旧的列,也可能遇到新的列,比如:

{  "文章":"课文2",  "作者":"李白",  "出版日期": "2022年7月6日"}
  • 1
  • 2
  • 3
  • 4
  • 5

这时,我们需要知道"文章" 和 “作者” 在第几列,同时也要知道 “出版日期” 应该在第几列,否则就不能确定唯一的单元格,将 JSON的value存储进去。

这里可以使用 Map<String, Integer> map 来记录列名以及下标。

在遍历对象时,key是列名,value则是单元格该填的值,如果 map.get(key) 的结果是空的,说明该列不存在,则需要创建,如果存在,那么可以创建单元格的对象,将值填入即可。

情形二:嵌套结构,JSON数组的嵌套

{  "班级A":[    {      "学号":"A01",      "语文":[        {          "文章":"课文1",          "作者":"李白"        },        {          "文章":"课文2",          "作者":"小李"        },        {          "文章":"课文2",          "作者": "小明"        }      ],      "数学":"130"    },    {      "学号":"A02",      "语文":"130",      "数学":"135"    }  ],}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

实现效果:

这里相比之前的情况复杂了一些,主要的就是需要再次创建一个新的 sheet,这意味着需要使用递归完成创建,于是我们可以将之前那种情形的代码实现封装成一个方法,比如createSubSheet(),在遍历JSON对象时,如果value值是一个JSONAarray,那么就再次调用createSubSheet()这个方法,只要使用同一个Workbook对象,表示同一个excel文件,就能满足这个需求了。

四、实现代码


pom.xml

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>groupId</groupId>    <artifactId>poi_demo</artifactId>    <version>1.0-SNAPSHOT</version>    <properties>        <maven.compiler.source>8</maven.compiler.source>        <maven.compiler.target>8</maven.compiler.target>    </properties>    <dependencies>        <dependency>            <groupId>org.apache.poi</groupId>            <artifactId>poi-ooxml</artifactId>            <version>5.2.2</version>        </dependency>        <dependency>            <groupId>org.apache.commons</groupId>            <artifactId>commons-lang3</artifactId>            <version>3.9</version>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>2.0.7</version>        </dependency>    </dependencies></project>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

JSONToExcelUtil.java

package cn.uni;import com.alibaba.fastjson2.JSON;import com.alibaba.fastjson2.JSONArray;import com.alibaba.fastjson2.JSONObject;import com.alibaba.fastjson2.JSONWriter;import com.alibaba.fastjson2.schema.JSONSchema;import org.apache.commons.io.FileUtils;import org.apache.commons.lang3.StringUtils;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.xssf.usermodel.XSSFCell;import org.apache.poi.xssf.usermodel.XSSFRow;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.*;import java.util.HashMap;import java.util.Map;/** *  uni *  2022/07/05~2022/07/06 *  将 JSON 转化为 Excel的工具类 */public class JSONToExcelUtil {    /**     * 读取绝对路径下的json文件     * @param resourcePath json文件的绝对路径     * @return json文件格式化后的字符串     */    public static String readJSONFile(String resourcePath) {        try{            // 1. 创建文件流            File file = new File(resourcePath);            // 2. 使用 common-lang3工具包, 以 UTF-8 格式读取文件, 转为字符串            String str = FileUtils.readFileToString(file, "UTF-8");            JSONObject jsonObject = JSONObject.parseObject(str);            // 3. 将字符串转为标准的JSON格式的字符串            return JSONObject.toJSONString(jsonObject, JSONWriter.Feature.WriteMapNullValue);        } catch (IOException e) {            throw new RuntimeException(e);        }    }    /**     * 创建 Sheet     * @param layer 当前Sheet所在JSON中的层级     * @param workbook 工作台 ( excel表格的主体 )     * @param sheetName 当前页的名称     * @param jsonArray JSON数组     */    public static void createSubSheet(int layer, XSSFWorkbook workbook, String sheetName, JSONArray jsonArray){        // 创建新的 sheet        XSSFSheet sheet = workbook.createSheet(sheetName);        // 存储每个字段        Map<String, Integer> map = new HashMap<>();        // 统计当前的列        int cellCount = 0;        // 创建第一行        XSSFRow firstRow = sheet.createRow(0);        // 获取每一项        for (int row = 1; row <= jsonArray.size(); row++) {            JSONObject jsonObject = jsonArray.getJSONObject(row - 1);            // 创建行            XSSFRow currentRow = sheet.createRow(row);            if(jsonObject != null){                // 遍历每个KV                for (String cellName : jsonObject.keySet()) {                    // 列不存在时, 则创建列                    if (!map.containsKey(cellName)) {                        // 第一行创建列                        XSSFCell firstRowCell = firstRow.createCell(cellCount);                        firstRowCell.setCellValue(cellName);                        map.put(cellName, cellCount++);                    }                    // 设置单元格                    XSSFCell cell = currentRow.createCell(map.get(cellName));                    // 获取 Value                    String cellValue = JSON.toJSONString(jsonObject.get(cellName));                    // 如果V为数组则递归创建sheet                    if(JSON.isValidArray(cellValue)){                        String subCellName = sheetName + "-" + cellName;                        cell.setCellValue(subCellName);                        createSubSheet(layer + 1, workbook,subCellName, jsonObject.getJSONArray(cellName));                    }                    else{                        cell.setCellValue(jsonObject.getString(cellName));                    }                }            } else{ // Value为一个数组                JSONArray array = jsonArray.getJSONArray(row - 1);                // 遍历数组                if(array != null && array.size() > 0){                    for (int i = 1; i <= array.size(); i++) {                        JSONObject obj = array.getJSONObject(i - 1);                        // 遍历 obj                        for (String cellName : obj.keySet()) {                            // 若列不存在则添加                            if(!map.containsKey(cellName)){                                XSSFCell cell = firstRow.createCell(cellCount);                                map.put(cellName, cellCount++);                                cell.setCellValue(cellName);                            }                            // 分情况讨论                            String cellValue = obj.getString(cellName);                            XSSFCell cell = currentRow.createCell(map.get(cellName));                            // 如果值是JSON对象, 则递归创建                            if(JSON.isValidObject(cellValue)){                                String subSheetName = sheetName + "-" + cellName;                                cell.setCellValue(subSheetName);                                createSubSheet(layer+1, workbook, subSheetName , JSONObject.parseObject(cellValue));                            } else if(JSON.isValidArray(cellValue)){                                String subSheetName = sheetName + "-" + cellName;                                cell.setCellValue(subSheetName);                                createSubSheet(layer+1, workbook, subSheetName , JSONArray.parseArray(cellValue));                            } else {                                cell.setCellValue(cellValue);                            }                        }                    }                } else {                    firstRow.createCell(0).setCellValue(sheetName);                    XSSFCell cell = currentRow.createCell(cellCount);                    cell.setCellValue(jsonArray.getString(row-1));                }            }        }    }    /**     * 创建 Sheet     * @param layer 当前Sheet所在JSON中的层级     * @param workbook 工作台 ( excel表格的主体 )     * @param sheetName 当前页的名称     * @param jsonObject JSON对象     */    public static void createSubSheet(int layer, XSSFWorkbook workbook, String sheetName, JSONObject jsonObject){        // 创建新的 sheet        XSSFSheet sheet = workbook.createSheet(sheetName);        // 存储每个字段        Map<String, Integer> map = new HashMap<>();        // 统计当前的列        int cellCount = 0;        // 创建第一行        XSSFRow fistRow = sheet.createRow(0);        // 记录行数        int row = 1;        // 获取每一项        // 创建行        XSSFRow currentRow = sheet.createRow(row);        // 遍历每个KV        for (String cellName : jsonObject.keySet()) {            // 列不存在时, 则创建列            if (!map.containsKey(cellName)) {                // 第一行创建列                XSSFCell firstRowCell = fistRow.createCell(cellCount);                firstRowCell.setCellValue(cellName);                map.put(cellName, cellCount++);            }            // 设置单元格            XSSFCell cell = currentRow.createCell(map.get(cellName));            // 获取 Value            String cellValue = JSON.toJSONString(jsonObject.get(cellName));            // 如果V为对象则递归创建sheet            if(JSON.isValidObject(cellValue)){                String subCellName = "Sheet" + layer + "-" + sheetName + "-" + cellName;                cell.setCellValue(subCellName);                createSubSheet(layer + 1, workbook,subCellName, JSON.parseObject(cellValue));            } else if(JSON.isValidArray(cellValue)){                String subCellName = "Sheet" + layer + "-" + sheetName + "-" + cellName;                cell.setCellValue(subCellName);                createSubSheet(layer + 1, workbook,subCellName, JSON.parseArray(cellValue));            }            else{                cell.setCellValue(jsonObject.getString(cellName));            }        }    }    /**     * 将格式化的JSON字符串导出为Excel     * @param jsonStr 格式化后的JSON字符串     * @param savePath Excel保存路径     * @param excelName Excel名称     */    public static void toExcelByString(String jsonStr, String savePath, String excelName){        assert JSON.isValid(jsonStr) : "字符串: " + jsonStr + " 不是标准的JSON字符串";        toExcelByJSONObject(JSONObject.parseObject(jsonStr),savePath, excelName);    }    /**     * 将普通的Java对象导出为JSON文件     * @param obj   Java对象     * @param savePath  Excel保存路径     * @param excelName Excel名称     */    public static void toExcelByObject(Object obj, String savePath, String excelName){        String jsonStr = JSON.toJSONString(obj, JSONWriter.Feature.WriteMapNullValue);        JSONObject jsonObject = JSONObject.parseObject(jsonStr);        toExcelByJSONObject(jsonObject, savePath, excelName);    }    /**     * 将本地的JSON文件导出为 Excel     * @param resourcePath JSON文件的绝对路径     * @param savePath  保存的路径     * @param excelName 保存的Excel名称     */    public static void toExcelByLocalJSONFile(String resourcePath, String savePath, String excelName){        // 1. 获取标准的 JSON 字符串        String jsonStr = readJSONFile(resourcePath);        // 验证字符串是否合法        assert JSON.isValid(jsonStr) : "路径:[" + resourcePath + "] 的json文件不符合标准的JSON格式";        toExcelByString(jsonStr, savePath, excelName);    }    /**     * 将JSONObject转化导出到 Excel     * 这里遵循递归导出,当遇到数组时会调用 createSheet创建新的页面。     * @param jsonObject    JSON对象     * @param savePath      Excel保存路径     * @param excelName     Excel名称     */    public static void toExcelByJSONObject(JSONObject jsonObject,  String savePath, String excelName){        try(XSSFWorkbook workbook = new XSSFWorkbook()){            // 获取当前的Sheet            XSSFSheet sheet = workbook.createSheet("sheet");            // 获取第一行            XSSFRow firstRow = sheet.createRow(0);            // 记录Key所在的列            Map<String, Integer> map = new HashMap<>();            // 记录列数            int cellCount = 0;            // 遍历 JSON的key            XSSFRow currentRow = sheet.createRow(1);            for (String key : jsonObject.keySet()) {                // 先处理列                if(!map.containsKey(key)){  // 当列不存在则添加                    map.put(key, cellCount);                    XSSFCell cell = firstRow.createCell(cellCount++);                    cell.setCellValue(key);                }                XSSFCell currentCell = currentRow.createCell(map.get(key));                String jsonStr = jsonObject.getString(key);                // 如果 Value为数组 则创建新的 Sheet                if(JSON.isValidArray(jsonStr)){                    String subSheetName = "Sheet-" + key;                    createSubSheet(1, workbook, subSheetName, jsonObject.getJSONArray(key));                    currentCell.setCellValue(subSheetName);                } else if(JSON.isValidObject(jsonStr)){ // 如果当前 value 仍然是一个JSON对象                    String subSheetName = "Sheet-" + key;                    createSubSheet(1, workbook, subSheetName, jsonObject.getJSONObject(key));                    currentCell.setCellValue(subSheetName);                }                else {                    // 特殊处理空值                    if(StringUtils.isEmpty(jsonStr))                        currentCell.setCellValue("null");                    else                        currentCell.setCellValue(jsonStr);                }            }            save(workbook, savePath, excelName);        } catch (IOException ex) {            throw new RuntimeException(ex);        }    }    /**     * 将 Excel对象保存到本地     * @param workbook Excel对象     * @param path Excel文件路径     * @param excelName excel名称     */    public static void save(Workbook workbook, String path, String excelName){        try {            FileOutputStream fileOutputStream = new FileOutputStream(path +"/" + excelName +".xlsx");            workbook.write(fileOutputStream);            fileOutputStream.close();            System.out.println("保存完毕. 保存位置为[ " + path + "/" + excelName + " ]");        } catch (IOException e) {            throw new RuntimeException(e);        }    }    public static void main(String[] args) {        String jsonPath = "C:\\Users\\unirithe\\IdeaProjects\\poi_demo\\src\\main\\resources\\data.json";        String savePath = "C:\\Users\\unirithe\\Desktop";        String excelName = "demo";        // 测试1        toExcelByLocalJSONFile(jsonPath, savePath, excelName + "1");        String jsonStr = readJSONFile(jsonPath);        JSONObject jsonObject = JSONObject.parseObject(jsonStr);        Object object = JSON.parse(jsonStr);        // 测试2        toExcelByString(jsonStr, savePath, excelName + "2");        // 测试3        toExcelByObject(object, savePath, excelName + "3");        // 测试4        toExcelByJSONObject(jsonObject, savePath, excelName + "4");    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303

测试的JSON数据:

{  "班级A":[    {      "学号":"A01",      "语文":[        {          "文章":"课文1",          "作者":"李白"        },        {          "文章":"课文2",          "作者":"小李"        },        {          "文章":"课文2",          "作者": "小明"        }      ],      "数学":"130"    },    {      "学号":"A02",      "语文":"130",      "数学":"135"    }  ],  "班级B":[    {      "学号":"B01",      "语文":"128",      "数学":"135"    },    {      "学号":"B02",      "语文":"133",      "数学":"140"    }  ]}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

测试结果如下,这里保存的demo1、demo2、demo3和demo4结果是一致的,主要是为了测试不同方法的正确性。




网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发