前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手把手教你JSON解析完Cube数据,如何输出到Excel

手把手教你JSON解析完Cube数据,如何输出到Excel

作者头像
大数据梦想家
发布2021-01-27 16:33:39
1.3K0
发布2021-01-27 16:33:39
举报

写在前面: 博主是一名大数据行业的追梦人,昵称来源于《爱丽丝梦游仙境》中的Alice和自己的昵称。作为一名互联网小白,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于起步阶段的萌新。由于水平有限,博客中难免会有一些错误,有纰漏之处恳请各位大佬不吝赐教!个人小站:http://alices.ibilibili.xyz/ , 博客主页:https://alice.blog.csdn.net/ 尽管当前水平可能不及各位大佬,但我还是希望自己能够做得更好,因为一天的生活就是一生的缩影。我希望在最美的年华,做最好的自己

最近公司有一个需求,需要解析Kylin上某个Cube的JSON格式的数据,并输出到Excel文件中。

我们先来看看这个Cube内部都有些什么?

这里我以其中一个JSON文件为例

在这里插入图片描述
在这里插入图片描述

是不是JSON内部的层级关系有点混乱,没关系,我们将里面的内容放到网页上去解析看看。

在这里插入图片描述
在这里插入图片描述

我们想要操作的是 key值为 indexes下的数组,并对 key = layouts 下的 idcol_order集合 拿出来,并对col_order集合中的元素做一个过滤,只获取其中 < 100000的元素,并将其输出到 Excel 文件中。

在这里插入图片描述
在这里插入图片描述

现在似乎需求已经看懂了,那我们就开始上手代码吧。

在这里插入图片描述
在这里插入图片描述

首先我们先创建一个 Maven 项目,因为涉及到JSON的解析,我们先在Pom中导入相关坐标:

代码语言:javascript
复制
<dependencies>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20090211</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>
    </dependencies>

然后我们创建一个ParseJson类,在main方法中,我们先定义好动态参数。

代码语言:javascript
复制
        // 输入路径
        String fileIntputPath = "G:\\idea arc\\ParseJson\\src\\main\\resources\\test.json";
        
        // 输出路径
        String fileOutputPath = "G:\\idea arc\\ParseJson\\src\\main\\resources\\writeTest2.xlsx";
        
        // 限制大小
        int limitNumber = 100000;

因为我们需要根据 指定的输入路径 去本地读取 JSON数据,所以我们还需要写一个方法。

代码语言:javascript
复制
/**
     * 读取指定文件路径的内容
     * @param filePath 文件路径
     * @return 文件内容
     */
    private  static String readJsonFile(String filePath) {
        String jsonStr = "";
        try {
            File jsonFile = new File(filePath);
            FileReader fileReader = new FileReader(jsonFile);
            Reader reader = new InputStreamReader(new FileInputStream(jsonFile),"utf-8");
            int ch = 0;
            StringBuilder sb = new StringBuilder();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

有了读取文件内容的方法,我们就可以在接下来自己书写一个解析 JSON 文件的方法了。根据刚在网页上展示的层级关系图,我们不难得出写出以下代码:

代码语言:javascript
复制
        // 调用方法,获取到指定路径的文件内容
        String str = readJsonFile(filePath);
          
        // 调用 JSON 库的内容,获取到解析的对象
        JSONObject jsonObject = JSON.parseObject(str);

        // 获取到 indexes 数组
        JSONArray jsonArray = jsonObject.getJSONArray("indexes");
        for (Object o : jsonArray) {

            JSONArray layouts = ((JSONObject) o).getJSONArray("layouts");

            for (Object layout : layouts) {

                int id = ((JSONObject) layout).getIntValue("id");

                JSONArray colOrder = ((JSONObject) layout).getJSONArray("col_order");

                // 定义一个 StringBuilder,用于保存每次累加的结果
                StringBuilder stringBuilder = new StringBuilder();

                // 定义一个字段 size 保存原来数组的长度
                int size = colOrder.size();
                // 调用自己写的静态方法,获取到满足需求的数组长度
                int greaterThanlakh = getGreaterThan(colOrder, size,limitNumber);
                // 定义一个字段保存每次循环的次数
                int loopCount = 0;

                for (Object o1 : colOrder) {
                    // 每循环一次,loopCount数值+1
                    loopCount ++;
                    // 将其转换成 int 类型的数字
                    int number = Integer.parseInt(o1.toString());

                    if(number < 100000){
                        if (loopCount==greaterThanlakh){
                            stringBuilder.append(number);
                        }else{
                            stringBuilder.append(number).append(",");
                        }
                    }
                }
            }
        }
           }

在这个过程中,因为涉及到判断一个数组中,元素没有被过滤的个数,所以又自己写的一个功能方法。

代码语言:javascript
复制
    /**
     * 计算出元素中小于100000的元素个数
     * @param jsonArray   JSON数组
     * @param size   JSON数组的容量大小
     * @param limitNumber   过滤条件
     * @return   小于100000的元素个数
     */
    private static int getGreaterThan (JSONArray jsonArray,int size,int limitNumber){

        // 定义一个变量保存数组中 > 100000 的元素个数
        int numberCount = 0;

        for (Object o : jsonArray) {
            int number = Integer.parseInt(o.toString());
            if (number >= limitNumber){
                numberCount ++;
            }
        }
       return size - numberCount;
    }

现在我们已经获取到了每一个id ,以及它所对应小于 100000 的 col_order数组中的元素。那么我们就应该开始考虑一下,如何将这些值输出到Excel文件中。

在这里插入图片描述
在这里插入图片描述

可能熟悉Java的朋友能马上想起来 POI

poi 组件是由Apache提供的组件包,主要职责是为我们的Java程序提供对于office文档的相关操作。

但是像菌这样的小白,一看到这些常用的类,还不吓得原地昏厥。

在这里插入图片描述
在这里插入图片描述

所以说,这辈子都不可能用的。但是需求还没完全实现,我们该怎么办呢?

正当本菌一筹莫展之际,突然在经友人的提醒下,想起了在GitHub上一个神奇的仓库。

https://github.com/looly/hutool

可以看到,目前该开源项目,已经斩获了 15.3k Star。

在这里插入图片描述
在这里插入图片描述

该仓库中包含了对大部分常用功能的代码封装。

在这里插入图片描述
在这里插入图片描述

根据作者介绍,Hutool 的存在就是为了减少代码搜索成本,避免网络上参差不齐的代码出现导致的bug。

关于 Hutool 在 maven 项目中的使用也非常简单,我们只需要在项目的pom.xml的dependencies中加入以下内容:

代码语言:javascript
复制
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.4.1</version>
</dependency>

关于更多 Hutool 的具体使用,我们可以去参考 中文手册

因为我们需要参考如何生成Excel,我们可以定位到这个位置

在这里插入图片描述
在这里插入图片描述

这里我将它的使用例子贴出来:

使用例子

1、将行列对象写出到Excel

我们先定义一个嵌套的List,List的元素也是一个List,内层的一个List代表一行数据,每行都有4个单元格,最终list对象代表多行数据。

代码语言:javascript
复制
List<String> row1 = CollUtil.newArrayList("aa", "bb", "cc", "dd");
List<String> row2 = CollUtil.newArrayList("aa1", "bb1", "cc1", "dd1");
List<String> row3 = CollUtil.newArrayList("aa2", "bb2", "cc2", "dd2");
List<String> row4 = CollUtil.newArrayList("aa3", "bb3", "cc3", "dd3");
List<String> row5 = CollUtil.newArrayList("aa4", "bb4", "cc4", "dd4");

List<List<String>> rows = CollUtil.newArrayList(row1, row2, row3, row4, row5);

然后我们创建ExcelWriter对象后写出数据:

代码语言:javascript
复制
//通过工具类创建writer
ExcelWriter writer = ExcelUtil.getWriter("d:/writeTest.xlsx");
//通过构造方法创建writer
//ExcelWriter writer = new ExcelWriter("d:/writeTest.xls");

//跳过当前行,既第一行,非必须,在此演示用
writer.passCurrentRow();

//合并单元格后的标题行,使用默认标题样式
writer.merge(row1.size() - 1, "测试标题");
//一次性写出内容,强制输出标题
writer.write(rows, true);
//关闭writer,释放内存
writer.close();

运行一下程序,我们观察案例代码实现的效果,打开 writeTest.xlsx

在这里插入图片描述
在这里插入图片描述

可谓是非常的 nice,我们只需要根据案例代码所给的提示把我们之前的代码 "完善"一下就好了。

但是还需要注意一点的就是,

Hutool-poi是针对Apache POI的封装,因此需要用户自行引入POI库,Hutool默认不引入。到目前为止,Hutool-poi支持:

  • Excel文件(xls, xlsx)的读取(ExcelReader)
  • Excel文件(xls,xlsx)的写出(ExcelWriter)

如果我们想要输出Excel,推荐引入poi-ooxml,这个包会自动关联引入poi包,且可以很好的支持Office2007+的文档格式

代码语言:javascript
复制
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>${poi.version}</version>
</dependency>

如果需要使用Sax方式读取Excel,需要引入以下依赖:

代码语言:javascript
复制
<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>${xerces.version}</version>
</dependency>

说明 hutool-4.x的poi-ooxml 版本需高于3.17(别问我3.8版本为啥不行,因为3.17 > 3.8 ) hutool-5.x的poi-ooxml 版本需高于 4.1.2 xercesImpl版本高于2.12.0

引入后即可使用Hutool的方法操作Office文件了,下面贴出正式的代码:

代码语言:javascript
复制
package com.czxy;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.io.*;
import java.util.List;

/**
 * @Author: Alice菌
 * @Date: 2020/9/7 18:27
 * @Description:
 */
public class ParseJson {
    public static void main(String[] args) throws Exception {


        // 输入路径
        //String fileIntputPath = "G:\\idea arc\\ParseJson\\src\\main\\resources\\test.json";
        String fileIntputPath = args[0];
        // 输出路径
        //String fileOutputPath = "G:\\idea arc\\ParseJson\\src\\main\\resources\\writeTest2.xlsx";
        String fileOutputPath = args[1];
        // 限制大小
        //int limitNumber = 100000;
        int limitNumber = Integer.parseInt(args[2]);

        strWriteToJSONObject(fileIntputPath,fileOutputPath,limitNumber);

    }

    /**
     * 读取指定文件路径的内容
     * @param filePath 文件路径
     * @return 文件内容
     */
    private  static String readJsonFile(String filePath) {
        String jsonStr = "";
        try {
            File jsonFile = new File(filePath);
            FileReader fileReader = new FileReader(jsonFile);
            Reader reader = new InputStreamReader(new FileInputStream(jsonFile),"utf-8");
            int ch = 0;
            StringBuilder sb = new StringBuilder();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private  static  void strWriteToJSONObject(String filePath,String fileOutPut,int limitNumber) throws Exception {

        // 调用方法,获取到指定路径的文件内容
        String str = readJsonFile(filePath);

        // 调用 JSON 库的内容,获取到解析的对象
        JSONObject jsonObject = JSON.parseObject(str);

        // 获取到 indexes 数组
        JSONArray jsonArray = jsonObject.getJSONArray("indexes");

        //如果需要输出到 txt 文本中,则使用下面这种方式
        //FileWriter fw = new FileWriter(fileOutPut, true);
        //BufferedWriter bw = new BufferedWriter(fw);

        //初始化一个集合,用于存储所有需要输出到Excel的列
        List<List<String>> rows = CollUtil.newArrayList();

        for (Object o : jsonArray) {

            JSONArray layouts = ((JSONObject) o).getJSONArray("layouts");

            for (Object layout : layouts) {

                int id = ((JSONObject) layout).getIntValue("id");

                JSONArray colOrder = ((JSONObject) layout).getJSONArray("col_order");

                // 定义一个 StringBuilder,用于保存每次累加的结果
                StringBuilder stringBuilder = new StringBuilder();

                // 定义一个字段 size 保存原来数组的长度
                int size = colOrder.size();
                // 调用自己写的静态方法,获取到满足需求的数组长度
                int greaterThanlakh = getGreaterThan(colOrder, size,limitNumber);

                // 定义一个字段保存每次循环的次数
                int loopCount = 0;

                for (Object o1 : colOrder) {
                    // 每循环一次,loopCount数值+1
                    loopCount ++;
                    // 将其转换成 int 类型的数字
                    int number = Integer.parseInt(o1.toString());

                    if(number < 100000){
                        if (loopCount==greaterThanlakh){
                            stringBuilder.append(number);
                        }else{
                            stringBuilder.append(number).append(",");
                        }
                    }
                }

                     List<String> row = CollUtil.newArrayList(id+"",stringBuilder.toString());
                     rows.add(row);


            }
        }
       OutToExcel(rows,fileOutPut);
    }

    /**
     * 计算出元素中小于100000的元素个数
     * @param jsonArray   JSON数组
     * @param size   JSON数组的容量大小
     * @param limitNumber   过滤条件
     * @return   小于100000的元素个数
     */
    private static int getGreaterThan (JSONArray jsonArray,int size,int limitNumber){

        // 定义一个变量保存数组中 > 100000 的元素个数
        int numberCount = 0;

        for (Object o : jsonArray) {
            int number = Integer.parseInt(o.toString());
            if (number >= limitNumber){
                numberCount ++;
            }
        }
       return size - numberCount;
    }
     
    public static void OutToExcel(List<List<String>> rows,String fileOutPut){
        for (List<String> row : rows) {
            System.out.println(row);
        }
        System.out.println("fileOutPath:"+fileOutPut);
        //通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(fileOutPut);
        //通过构造方法创建writer
        //ExcelWriter writer = new ExcelWriter("d:/writeTest.xls");

        //跳过当前行,既第一行,非必须,在此演示用
        //writer.passCurrentRow();

        //合并单元格后的标题行,使用默认标题样式
        //writer.merge(row1.size() - 1, "测试标题");
        //一次性写出内容,强制输出标题
        writer.write(rows, true);
        //关闭writer,释放内存
        writer.close();
    }
    }

细心的朋友们可能已经发现,博主已经将 main 方法中的变量替换成了参数,主要的目的就是可以将代码打包到Linux上运行,就像这样。

在这里插入图片描述
在这里插入图片描述

这里我们打开 outToExcel.xlsx 文件,看下效果。

在这里插入图片描述
在这里插入图片描述

小结

本篇博客,博主主要为大家介绍了如何通过Json去解析Cube中的数据,并将需要的数据输出到Excel当中。菌着重为大家安利了一款非常实用的工具库——hutool,希望大家都能在不断探索的过程中,发现一些新鲜好玩的东西。

如果以上过程中出现了任何的纰漏错误,烦请大佬们指正?

受益的朋友或对大数据技术感兴趣的伙伴记得点赞关注支持一波?

希望我们都能在学习的道路上越走越远?

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用例子
    • 1、将行列对象写出到Excel
    • 小结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档