json大文件打开与美化

背景

之前对接一个第三方的组织机构同步接口,选择全量同步时,它响应的json数据竟然有100多M。
虽然对方提供了接口文档,但是死脑筋的我,还是来来回回折腾了好久。
这里记录下遇到的问题和解决方案。

问题1:Postman响应大小限制

Postman响应大小设置

  • 我先用postman去调了一个下接口,然后发现postman居然有一个响应大小限制,默认50M。

  • 修改默认配置前,请求失败

    image-20230218225602018
  • 在File–>Setting,打开设置页修改

  • 改为0,则是不限制

    image-20230218225718637

问题2:怎么看响应数据:postman将响应导出为文件

  • 因为内容太过巨大,postman完全无法美化。

  • 这个时候可以把响应导出为文件,然后用文本编辑器打开查看。

    image-20230218230246939

问题3:用什么文本编辑器来打开大型文本文件

方式一:idea(不推荐)

  • idea针对大文件,默认只预览前面一部分的内容,而且是只读模式,不能编辑。

  • 通过改配置,可以打开,但是超级卡顿。

  • 再修改idea的内存大小限制,应该可以解决卡顿,但是没必要尝试了。

  • IDEA加载大文件时报错:The file size exceeds configured limit

    • 1.打开 help --> edit custom properties选项(注意区分VM Options), 如果本机没有这个文件会提示要先创建

    • 2.点击create按钮之后,在文件中添加如下语句(默认值2500即2.56m, 也可以自己设置一个值, 单位是k)

    • idea.max.intellisense.filesize=999999

      image-20230218232517175

方式二:Sublime Text3 (几百M的使用)

  • 网上说打开几百M的文件还行,打开1G以上的不推荐。

  • 可以安装插件,来美化或压缩json。

  • Sublime Text 下载和安装教程

    • 汉化设置
      • 1.快捷键ctrl+shift+p,弹出查找栏—找到 install Package,并点击选择
      • 2.再次弹出的框中,选择ChineseLocalizations或者Chinese,等待安装完毕即可(页面窗口会有提示的)
  • 直接操作压缩的json依然很卡,因为所有内容是在一行显示的,所以需要美化一下

  • sublime基本使用

  • sublime-text(格式化JSON数据)

    • 安装json格式化插件[Pretty JSON](https://packagecontrol.io/packages/Pretty JSON)
      • 1.Ctrl+Shift+P打开搜索面板,然后输入Install Package(Package Control:Install Package),连接仓库

      • 2.Ctrl+Shift+P打开搜索面板,选择Pretty Json

      • 3.Ctrl+Shift+P打开搜索面板,输入format,选择Format JSON格式化数据

      • 4.Pretty JSON:Minify JSON–>压缩数据

        image-20230218231833542

方式三:EmEditor (上G的使用)

java代码美化json,以及查看json数据结构

java代码

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import util.PythonUtil;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 格式化(美化)大json文件
 */
public class ParseJsonUtil {

    public static void main(String[] args) {
        // json文件存放目录
        String fileDir = "D:\\export_tmp";
        // json文件名称,不用带.json后缀
        String fileName = "用户部门数据";

        // json文件路径
        String jsonFilePath = fileDir + File.separator + fileName + ".json";
        // 格式化json文件(java代码)
        parseJsonFile(jsonFilePath, fileDir, fileName + "_java");

        // 格式化json文件(Python脚本)
        parseJsonByPython(jsonFilePath, null);

    }

    /**
     * 格式化json文件(java代码)
     *
     * @param filePath json文件地址
     */
    public static void parseJsonByPython(String filePath, String targetFilePath) {
        // 解释器
        String exe = "python";
        // python脚本路径,建议使用绝对路径
        // String command = "E:\\work\\项目\\java-learn-demo\\java-tools\\src\\main\\java\\json\\parseJson.py";
        String command = "java-tools\\src\\main\\java\\json\\parseJson.py";
        String sourceFilePath = filePath;
        if (targetFilePath == null) {
            targetFilePath = filePath.substring(0, filePath.lastIndexOf(".")) + "_python.json";
        }
        // 组合成一个字符串数组
        String[] cmdArr = new String[]{exe, command, sourceFilePath, targetFilePath};

        // 执行python脚本
        PythonUtil.executePythonScript(cmdArr);
    }

    /**
     * 格式化json字符串 alibaba.fastjson
     *
     * 使用Fastjson/Gson/Jackson美化json字符串格式 https://blog.51cto.com/hspbc/5052416
     * 利用fastjson美化json串的方法 https://blog.csdn.net/u010251278/article/details/91992618
     *
     * @param text
     * @return
     */
    private static String buildJson(String text) {
        // 可以直接在这里打断点debug,查看变量,即json数据的结构
        Object jsonobj = JSON.parse(text, Feature.AllowSingleQuotes);

        String jsonText = JSON.toJSONString(jsonobj, SerializerFeature.WriteMapNullValue, SerializerFeature.PrettyFormat);
        return jsonText;
    }

    /**
     * 生成.json格式文件
     * https://blog.csdn.net/J_M_S_H_T/article/details/126560693
     *
     * @param jsonString json字符串
     * @param fileDir    文件保存目录
     * @param fileName   json文件名称,不带.json后缀
     * @return
     */
    public static boolean createJsonFile(String jsonString, String fileDir, String fileName) {
        // 标记文件生成是否成功
        boolean flag = true;

        // 拼接文件完整路径
        String fullPath = fileDir + File.separator + fileName + ".json";

        // 生成json格式文件
        try {
            // 保证创建一个新文件
            File file = new File(fullPath);
            if (!file.getParentFile().exists()) { // 如果父目录不存在,创建父目录
                file.getParentFile().mkdirs();
            }
            if (file.exists()) { // 如果已存在,删除旧文件
                file.delete();
            }
            file.createNewFile();

            // 将格式化后的字符串写入文件
            Writer write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
            write.write(jsonString);
            write.flush();
            write.close();
            flag = true;
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }

        // 返回是否成功的标记
        return flag;
    }

    /**
     * 格式化json文件(java代码)
     *
     * @param jsonFilePath json文件地址
     */
    public static boolean parseJsonFile(String jsonFilePath, String fileDir, String fileName) {
        // 标记文件生成是否成功
        boolean flag = true;

        // 生成json格式文件
        try {
            // 保证创建一个新文件
            File file = new File(jsonFilePath);
            if (!file.exists()) {
                System.out.println("json文件不存在");
                return false;
            }
            String jsonString = readFileContent(file);
            if (jsonString == null) {
                System.out.println("文件内容为null");
                return false;
            }

           
            // 格式化json字符串方式 fastjson提供的方法
            jsonString = buildJson(jsonString);

            createJsonFile(jsonString, fileDir, fileName);
            flag = true;
        } catch (Exception e) {
            flag = false;
            e.printStackTrace();
        }

        // 返回是否成功的标记
        return flag;
    }

    /**
     * 读取文件内容
     * @param file
     */
    public static String readFileContent(File file) {
        BufferedReader reader = null;
        StringBuffer sbf = new StringBuffer();
        try (InputStreamReader in = new InputStreamReader(new FileInputStream(file),"UTF-8");) {
            reader = new BufferedReader(in);
            String tempStr;
            while ((tempStr = reader.readLine()) != null) {
                sbf.append(tempStr);
            }
            reader.close();
            return sbf.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return sbf.toString();
    }
}

python脚本

# -*- encoding: utf-8 -*-
# python parseJson.py dept2.json dept3.json
from sys import argv
class JsonFormatter:
    def __init__(self, intend=4, name="", outName="", encoding="utf-8"):
        '''
        intend: 缩进空格数
        name: 文件名
        encoding: 文件编码
        '''
        self.name = name
        self.outName = outName
        self.intend = intend
        self.encoding = encoding
        self.stack = []
        self.obj = None
        self.source = self.get_source(name, self.encoding)
        self.prepare()
    @staticmethod
    def json_str(s):
        '''
        给字符串套上双引号
        '''
        return '"' + s + '"'
    @staticmethod
    def get_source(name, encoding="utf-8"):
        with open(name, 'r', encoding=encoding) as f:
            # 当不给split函数传递任何参数时,分隔符sep会采用任意形式的空白字符:空格、tab、换行、回车以及换页符
            return ''.join(f.read().split())
    def prepare(self):
        try:
            # python对象和json格式还是略有不同
            self.source = self.source.replace("null", "None").replace("true", "True").replace("false", "False")
            self.obj = eval(self.source)
        except:
            # json string 一定满足python dict和list的组合
            raise Exception('Invalid json string!')
    def line_intend(self, level=0):
        return '\n' + ' ' * self.intend * level
    def parse_dict(self,obj=None,intend_level=0):
        if intend_level == 0:
            # 这个判断是为了防止文件开头出现空行
            self.stack.append('{')
        else:
            self.stack.append(self.line_intend(intend_level)+'{')
        intend_level += 1
        i = 0
        for key, value in obj.items():
            key = self.json_str(str(key))
            self.stack.append(self.line_intend(intend_level)+key+':')
            self.parse(value, intend_level)
            if i != len(obj.items())-1:
                # 这个处理是为了防止最后一对kv后面还有个逗号,这样会造成json.load()函数无法读取
                self.stack.append(',')
            i += 1
        self.stack.append(self.line_intend(intend_level-1)+'}')
    def parse_list(self, obj=None, intend_level=0):
        if intend_level == 0:
            self.stack.append('[')
        else:
            self.stack.append(self.line_intend(intend_level)+'[')
        intend_level += 1
        for i, item in zip(range(0, len(obj)), obj):
            self.parse(item, intend_level)
            if i != len(obj)-1:
                self.stack.append(',')
        self.stack.append(self.line_intend(intend_level-1)+']')
    def parse(self, obj, intend_level=0):
        if obj is None:
            self.stack.append('null')
        elif obj is True:
            self.stack.append('true')
        elif obj is False:
            self.stack.append('false')
        elif isinstance(obj, (int, float)):
            self.stack.append(str(obj))
        elif isinstance(obj, str):
            self.stack.append(self.json_str(obj))
        elif isinstance(obj, (list, tuple)):
            self.parse_list(obj, intend_level)
        elif isinstance(obj, dict):
            self.parse_dict(obj, intend_level)
        else:
            raise Exception('Invalid json type %s!' % obj)
    def render(self):
        self.parse(self.obj, 0)
        res_file = self.outName
        res = ''.join(self.stack)
        with open(res_file, 'w', encoding=self.encoding) as f:
            f.write(res)
if __name__ == "__main__":
    print('------------------------begin---------------------------')
    in_filename = argv[1]
    out_filename = argv[2]
    #jf = JsonFormatter(name="dept.json")
    jf = JsonFormatter(name=in_filename,outName=out_filename)
    jf.render()
    print('-------------------------end----------------------------')

java调用python脚本工具

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * python工具
 */
public class PythonUtil {

    /**
     * 执行python脚本
     * @param cmdArr cmd命令数组
     */
    public static void executePythonScript(String[] cmdArr) {
        if (cmdArr == null || cmdArr.length < 2) {
            // 参数缺失
            return;
        }
        try {
            // 创建进程对象并调用命令行执行python脚本代码
            final Process pr = Runtime.getRuntime().exec(cmdArr);
            // python中print到流中,因此java也从流中读取数据
            // 避免waitFor死锁,需要把读取放在waitFor()之前
            // https://www.ab62.cn/article/1672.html
            BufferedReader normalReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(pr.getErrorStream()));

            // readLine卡死
            // https://blog.csdn.net/jstlovely/article/details/121247764
            // Process.getInputStream()和Process.getErrorStream()分别返回Process的标准输出流和错误流,两个流如果处理不当,其缓冲区不能被及时清除而被塞满,则进程会被阻塞
            // 两个流需要同时读取
            // 防止缓冲区满, 导致卡住
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    String line;
                    try {
                        // GBK 解决中文乱码
                        BufferedReader stderr = new BufferedReader(new InputStreamReader(pr.getErrorStream(), "GBK"));
                        while ((line = stderr.readLine()) != null) {
                            System.out.println("stderr:" + line);
                        }
                    } catch (Exception e) {

                    }

                }
            }.start();

            System.out.println("==============打印结果==============");
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    String line;
                    try {
                        BufferedReader stdout = new BufferedReader(new InputStreamReader(pr.getInputStream(), "GBK"));
                        while ((line = stdout.readLine()) != null) {
                            System.out.println("stdout:" + line);
                        }
                    } catch (Exception e) {

                    }
                }
            }.start();

            // 使当前正在运行的线程在需要时等待,直到由该Process对象表示的进程完成其终止为止
            // https://blog.csdn.net/cumubi7453/article/details/107795393
            // 返回流程的退出值,当返回值0时,它反映了流程的正常终止
            int exitCode = pr.waitFor(); 
            System.out.println(exitCode);
            if (exitCode == 0) {
                System.out.println("脚本文件执行成功!");
            } else {
                System.out.println("脚本文件执行失败!");
            }
            // 关闭流
            errorReader.close();
            normalReader.close();
            pr.destroy();
            System.out.println("end");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

扩展:根据json字符生成Java实体类

  • 如果要使用到的json数据的属性比较多,建议建一个实体类,比如同步数据的时候。
  • 如果只是要判断结果是否成功,直接get名字也行。
  • 反正,怎么简单怎么来。

方式一:在线生成工具:bejson

方式二:IDEA插件-GsonFormatPlus(JSON转实体类bean)

方式三:java代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值