-
需求
api调用对为审批通过的字段进行网关剪切过滤,使用户只能看到申请的字段
例:原始json{ "aa": { "aaa": "aaa", "bbb": "bbb", "ccc": "ccc" }, "bb": { "aaa": "aaa", "bbb": "bbb", "ccc": "ccc" } }
裁减过滤后
{ "aa": { "aaa": "aaa" }, "bb": { "aaa": "aaa", "bbb": "bbb" } }
-
调研
方法一:根据字段递归遍历进行cut获取
方法二:json扁平化,删除节点后重组
方法三:jsonpath删除获取
方法四:自定义规则json解析器cut
方法五:JSLT技术 -
实现比对
- 方法一性能差,并且cpu、内存压力较大,代码不易维护,不考虑
- 方法二使用json-flattener github地址戳这
pom
api 详细的看github<dependency> <groupId>com.github.wnameless.json</groupId> <artifactId>json-flattener</artifactId> <version>0.11.1</version> </dependency>
删除不需要的key,然后扁平json化即可String json = "{\"abc\":{\"def\":[1,2,{\"g\":{\"h\":[3]}}]}}"; String flattenedJson = JsonFlattener.flatten(json); Map<String, Object> flattenedMap = JsonFlattener.flattenAsMap(json); Map<String, Object> unflattenedMap; unflattenedMap = JsonUnflattener.unflattenAsMap(flattenedJson); unflattenedMap = JsonUnflattener.unflattenAsMap(flattenedMap);
- 方法三 利用jsonpath的特性对json裁减,去除多余的节点
github地址:戳这
pom
api<dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.4.0</version> </dependency>
public static String cutJsonPath(String target, List<String> rules) throws IOException { if (Objects.isNull(rules) || rules.isEmpty()) { return target; } //根据删除json的jsonpath剪切json DocumentContext doc = JsonPath.parse(JSONUtil.parseObj(target)); for (String rule : rules) { doc.delete(rule, new Predicate[0]); log.debug("jsonPath delete path=[{}]", rule); } return doc.jsonString(); }
- 方法四:自定义裁减规则解析
github地址: 戳这
使用:两种方式: includes/excludesprivate static final JsonFactory JSON_FACTORY = new JsonFactory(); public void filter(Reader in, StringWriter out, String includes, String excludes) { Validate.notNull(in, "输入参数不能为空"); Validate.notNull(out, "输出参数不能为空"); try (JsonParser parser = JSON_FACTORY.createParser(in); JsonGenerator generator = JSON_FACTORY.createGenerator(out)) { FieldFilterTree tree = new FieldFilterParser(includes, excludes).parse(); JsonFilterParser jsp = new JsonFilterParser(parser, tree); while (jsp.nextToken() != null) { processToken(generator, jsp); } } catch (Exception e) { log.error("过滤JSON数据错误,includes=[{}], excludes=[{}]", includes, excludes); } }
我的github地址 源代码戳这//规则 String rule = "aa(aaa),bb(aaa,bbb)"; //使用,我做了封装 String rtn = jsonFilter.filterInclude(target, rule); String rule1 = "aa(bbb,ccc),bb(ccc)"; String rtn = jsonFilter.filterExclude(target, rule1);
综比较下选用第四种方法
性能测试如下
1M-----0.03ms
5M-----------0.1ms
30M---------0.5ms
50M---------1s
其实jsonpath在json tree不是很复杂的情况下花费时间不是很长也可以选用,具体的比较在我的git上有,大家可以看看,不过pom依赖不完整,只看代码即可
最后上线正式环境下jsonCut的时间平均为5ms左右,最大时间取决于cpu的资源,完美解决问题
方法五(后加的)
JSLT技术 https://github.com/schibsted/jslt
在线 demo 地址 https://www.garshol.priv.no/jslt-demo