jackson 使用jsonNode与objectNode 实现对 JSON串信息的读取,修改等操作

前情提要

因为现有项目都用的阿里巴巴的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

posted @ 2024-04-10 19:48  charler。  阅读(1411)  评论(0编辑  收藏  举报