背景
之前对接一个第三方的组织机构同步接口,选择全量同步时,它响应的json数据竟然有100多M。
虽然对方提供了接口文档,但是死脑筋的我,还是来来回回折腾了好久。
这里记录下遇到的问题和解决方案。
问题1:Postman响应大小限制
-
我先用postman去调了一个下接口,然后发现postman居然有一个响应大小限制,默认50M。
-
修改默认配置前,请求失败
-
在File–>Setting,打开设置页修改
-
改为0,则是不限制
问题2:怎么看响应数据:postman将响应导出为文件
-
因为内容太过巨大,postman完全无法美化。
-
这个时候可以把响应导出为文件,然后用文本编辑器打开查看。
问题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
-
方式二:Sublime Text3 (几百M的使用)
-
网上说打开几百M的文件还行,打开1G以上的不推荐。
-
可以安装插件,来美化或压缩json。
-
- 汉化设置
- 1.快捷键ctrl+shift+p,弹出查找栏—找到 install Package,并点击选择
- 2.再次弹出的框中,选择ChineseLocalizations或者Chinese,等待安装完毕即可(页面窗口会有提示的)
- 汉化设置
-
直接操作压缩的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–>压缩数据
-
- 安装json格式化插件[Pretty JSON](https://packagecontrol.io/packages/Pretty JSON)
方式三:EmEditor (上G的使用)
-
针对这个软件,B站有个up主录了很多教程;EmEditor系列教程-03集-大文件打开与编辑
-
它有免费版,可以下载便携版(不需安装,解压即可使用)
-
解压之后 emed64_22.2.2_portable
-
初次打开,需要选择免费版,然后会提示你是否要降级免费版本
-
选是,重启
-
也可以从大眼仔下载绿色版:优秀代码编辑器 EmEditor Professional 22.2.0 + x64 中文免费版
java代码美化json,以及查看json数据结构
-
从网上找了2种方式
-
方式一:使用fastjson提供的美化方法,通过格式化json字符串,再打断点debug,还可以查看json数据的层次结构
-
方式二:使用java调用python脚本,python自带的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名字也行。
- 反正,怎么简单怎么来。