前情提要
因为现有项目都用的阿里巴巴的fastjson 做json串的序列化与反序列化, 但是fastJson的漏洞太多了, 经常处理扫描出来的漏洞时, 需要升级版本, 导致出现各种大大小小的bug, 经过考究, 决定使用jackSon 做新项目的序列化与反序列化工作, 那先看一下常用的场景:
将对象转为json串
初始化一个objectMapper
用writeValueAsString 方法将实体转为json串
public static String ObjToJson(Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(obj);
}
将json串转为指定对象
传个对象引用类型, 这样可以传复杂嵌套的结构, 并结构化出来, 举个栗子
new TypeReference<List<LinkedHashMap<String, String>>>(){};
把上面这个作为第二位参数传入, 即可获取到结构化后的实体,并且结构是指定的 List<LinkedHashMap<String, String>>
public static <T> T jsonParseToObj(String content, TypeReference<T> valueTypeRef) {
return objectMapper.readValue(content, valueTypeRef);
}
问题
如果我们不是直接拿着json串进行序列化反序列化操作, 而需要对暂存的json对象进行操作,比如增删改json串中节点的数据,那么之用fastJson时, 通过jsonObject 操作json串的操作,就可以非常方便的实现, 比如:
jsonObj.getString("xxx")
jsonObj.put("a", "b");
现在切换成jackson 之后, 按道理应该也有类似JsonObject 的类, 可以进行类型的操作, 简单研究了一下, 就到了今天的主角登场了, JsonNode 以及 ObjectNode, 使用JsonNode 是一个只读的类似JsonObject对象, 可以直接获取指定key的值等操作; ObjectNode 则支持修改内部值,可以用ObjectNode创建自定义的对象.
/**
* jsonStr 转 jsonNode 支持类似jsonObject的操作
* @param jsonString 待转换的json串
* @return json node
*/
public static JsonNode jsonToJsonNode(String jsonString) {
try {
return objectMapper.readTree(jsonString);
} catch (Exception e) {
log.error("json串转ObjectNode失败");
return null;
}
}
用上述方法可以将json串转换为JsonNode, 用下面的方法则可以将jsonNode 转为指定类的对象
/**
* jsonNode 转 对象
* @param node json 节点
* @param valueTypeRef 参考引用
* @return 转换后的class
* @param <T>
*/
public static <T> T JsonNodeToObject(JsonNode node, TypeReference<T> valueTypeRef) {
return objectMapper.convertValue(node, valueTypeRef);
}
那么获取到了一个json串,通过 jsonToJsonNode 转为jsonNode,我需要在指定Key的层,新增一个键值对, 可他又是只读的, 那咋办? 其实很简单, 直接将其强制转换为ObjectNode, 就能对其进行操作了,继续举个栗子
JsonNode jsonNode = this.jsonToJsonNode(json);
((ObjectNode) jsonNode).put("number", 1);
这样就能将其json串最外层的属性上新增一个 "number":1, 如果需要在里面的指定层操作的话,继续往下看:
JsonNode jsonNode = JsonUtil.jsonToJsonNode(json);
JsonNode fieldA = jsonNode.get("fieldA");
((ObjectNode) fieldA).put("number", 1);
- 如果需要创建"key": [xxx, xxx] (array) 的属性放进去, 可以用 ObjectNode.putArray("key") 方法 ,传属性名即可
- 如果要放不透明的java对象,则要用putPOJO方法
- 其他基础用法可以自行研究
JsonNode jsonNode = JsonUtil.jsonToJsonNode(json);
JsonNode fieldA = jsonNode.get("fieldA");
// 放 int
((ObjectNode) fieldA).put("int", 1);
// 放对象
((ObjectNode) fieldA).putPOJO("obj", invoice);
// 放array
ArrayNode arrayNode = ((ObjectNode) fieldA).putArray("array");
arrayNode.add("1");
arrayNode.add("2");
arrayNode.add("3");
可以看到,操作类似jsonObject对象的JsonNode 以及 ObjectNode 比起fastJson 确实复杂了一点, 但为了项目稳定性,还是值得一用的~
refer:
https://blog.csdn.net/ss_Tina/article/details/133633498
https://github.com/FasterXML/jackson-databind/tree/2.14?tab=security-ov-file
https://blog.csdn.net/L990616_ss/article/details/125928762