在工作中遇到了解析JSON数据的场景,但是此岗位传统的做法是通过Python脚本来实现的,而且是非常不合理的手动解析——每对应不同的JSON数据结构,都需要手动改动很多脚本文件,工作量与JSON数据结构的复杂程度成正比!(很难想象这是一个做开发的人想出来的方案)
因此最开始接触此工作内容的时候,我就忍不住吐槽该实现的各种繁琐之处,遂萌生了使用Java语言实现自动化解析复杂JSON数据的想法。
需求:
将复杂JSON数据解构为扁平化数据,插入数据库对应的一张表上,供业务更直观地查询/阅览数据。
思路:
使用Jackson将数据转成JsonNode对象,然后通过递归解构至JsonNode不在为对象为止,然后put到一个LinkedHashMap中去,以此实现数据结构的扁平化变换。
核心代码:
public void print(JsonNode jsonNode) {
Map<String, String> map = recursiveParse(jsonNode, new LinkedHashMap<>(), null);
map.forEach((key, value) -> System.err.prinln(key + ":" + value));
}
private Map<String, String> recursiveParse(JsonNode jsonNode, Map<String, String> map, String parentKey) {
if(jsonNode.isObject()){
jsonNode.fields().forEachRemaining(entry -> {
String currentKey = parentKey != null ? parentKey + "_" + entry.getKey() : entry.getKey();
recursiveParse(jsonNode, map, currentKey);
})
}
// 此前的经验:当JSON数据过于复杂时或Array的元素个数非常多时,Array结构若继续解析会导致一张表的字段数量过千
// 为避免此情况,因此遇到Array结构不再解析,而是单独对此Array解析到另一张表
else if(jsonNode.isArray()) {
map.put(parentKey, jsonNode.toString());
}
else {
map.put(parentKey, jsonNode.asText());
}
}
测试类验证:
@Autowired
private ObjectMapper objectMapper
@Autowired
private Xxxx xxxx;
@Test
public void testSth() {
JsonNode jsonNode = objectMapper.readValue(Temp.class.getClassLoader().getResourceAsStream("xx.json"), JsonNode.class);
xxxx.print(jsonNode);
}
经测试验证,和传统方式解析的效果一致,因此可以认为我的思路是对的,后续可以根据Map输出建表语句,然后由人工修改字段长度(这是无法避免的,除非你使用的数据库,字符串长度是可伸缩的)。
建好表以后,再拟定一个定时任务,读取JSON数据,解析,插入。(因为一些原因——守旧?,笔者的实现很可能无法应用于工作,因此后续的代码就没写了)
标签:map,jsonNode,Java,扁平化,JsonNode,JSON,解析,parentKey From: https://www.cnblogs.com/ashet/p/17980282