json格式是进行数据传输的一种常见的格式,尤其是在web开发中,http请求的body体一般都是json格式的,早些年xml格式是主流的数据传输格式,但逐渐被形式更加简洁明了的json格式取代。Java开源的json类库有很多种,比较常见的有:

  • fastjson
  • jackson
  • Gson
  • Json-lib

工作中遇到最多的是fastjson和jackson,因此本文重点介绍这两个json库。

1、fastjson

1.1 简介

FastJson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean,相比其他json类库,fastjson有以下特点:

  • 速度快,在简单对象和复杂对象的序列化和反序列化的速度上比第二名的jackson快了20%;
  • api使用简单,提供的api多是静态方法,相比jackson使用是需要新建实例对象,fastjson使用起来更加方便;
  • 有漏洞,在AutoType上存在漏洞,具体看参考链接2,所以有些公司禁止使用fastjson了,但感觉用的还是很多,之前华为倒是漏洞扫描时扫出来了很多还专门整改了。

maven依赖:

  1. <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
  2. <dependency>
  3. <groupId>com.alibaba</groupId>
  4. <artifactId>fastjson</artifactId>
  5. <version>1.2.73</version>
  6. </dependency>

1.2 数据结构

1.2.1 JSONObject && JSONArray

fastjson里针对json对象和数组设计了对应的数据结构:

  • JSONObject:一个json对象,即一个key:value组成的键值对,{},JSONObject类实现了Map接口,因此可以直接向JSONObject用put方法添加k-v;
  • JSONArray:一个json数组,由若干个JSONObject组成的数组,[{}, {}, {}],JSONArray类实现了List接口,因此可以直接向JSONArray用add方法添加JSON对象,其中getJSONObject(int index)方法用来获取指定下标的JSONObject对象。

举个例子:

package com.Jerry.json.fastjson;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

public class ObjectArrayDemo {
    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "jerry");
        jsonObject.put("age", 27);

        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.put("name", "Cissie");
        jsonObject1.put("age", 28);

        JSONArray jsonArray = new JSONArray();
        jsonArray.add(jsonObject);
        jsonArray.add(jsonObject1);

        System.out.println(jsonObject);
        System.out.println(jsonObject1);
        System.out.println(jsonArray);
    }
}

结果:

{"name":"jerry","age":27}
{"name":"Cissie","age":28}
[{"name":"jerry","age":27},{"name":"Cissie","age":28}]

1.2.2 api使用

  • 判断JSONObject里是否含有指定的key

    jsonObject.containsKey("key")
    

    这个方法是Map接口的,JSONObject实现了Map接口,在HashMap里也有containsKey方法。

  • 从复杂的JSONObject里获取子JSONObject

    String str = "{\"courses\":[{\"courseName\":\"Math\",\"score\":99},{\"courseName\":\"Computer\"," +
                  "\"score\":100},{\"courseName\":\"English\",\"score\":98}],\"dog\":{\"color\":\"white\",\"dogAge\":1,\"dogName\":\"miumiu\",\"variety\":\"British Shorthair Cat\"},\"id\":\"ff6e8dec-630f-47ad-b1f2-99e739cea49d\",\"studentAge\":27,\"studentName\":\"Jerry\"}";
    JSONObject jsonObject = JSON.parseObject(str);
    JSONObject jsonObject1 = jsonObject.getJSONObject("dog");
    
  • 从复杂的JSONObject里获取子JSON字符串

    String str = "{\"courses\":[{\"courseName\":\"Math\",\"score\":99},{\"courseName\":\"Computer\"," +
                  "\"score\":100},{\"courseName\":\"English\",\"score\":98}],\"dog\":{\"color\":\"white\",\"dogAge\":1,\"dogName\":\"miumiu\",\"variety\":\"British Shorthair Cat\"},\"id\":\"ff6e8dec-630f-47ad-b1f2-99e739cea49d\",\"studentAge\":27,\"studentName\":\"Jerry\"}";
    JSONObject jsonObject = JSON.parseObject(str);
    String str1 = jsonObject.getString("dog");
    
  • JSONObject转字符串

    String str = jsonObject.toJSONString();
    

    toJSONString底层实现还是Object类的toString方法。

  • 字符串转JSONObject

    JSONObject jsonObject = JSON.parseObject(str);
    
  • JSONObject转JavaBean

暂无直接的api,可以用JSONObject -> JSONString -> JavaBean。

  • JavaBean转JSONObject

暂无直接的api,可以用JavaBean-> JSONString -> JSONObject 。

  • 将JSON的字符串数组转换成JSONArray

    JSONArray jsonArray = JSON.parseArray(JSON_ARRAY_STR);
    
  • 将JSONArray转换成JSON的字符串数组

    String s = JSON.toJSONString(jsonArray);
    

    上面的api工作中用的不多,最多的还是下面的序列化反序列化和@JSONField注解。

  • entrySet()

由于JSONObject实现了Map接口,因此Map的一些方法,比如entrySet()、containsKey()在JSONObject里也有实现。

1.3 序列化&&反序列化

  • 序列化:将JavaBean转换成JSON字符串,使用JSON.toJSONString(JavaBean);
  • 反序列化:将JSON字符串转换成JavaBean,使用JSON.parseObject(str, JavaBean.class())。

举例:
Dog的JavaBean:

@Data
public class Dog {
    private String dogName;
    private int dogAge;
    private String color;
    private String variety;
}

Course的JavaBean:

@Data
@AllArgsConstructor
public class Course {
    private String courseName;
    private int score;
}

需要序列化的Student的JavaBean:

@Data
public class Student {
    private String studentName;
    private int studentAge;
    private String id;
    private List<Course> courses;
    private Dog dog;
}

把Student实例的初始化动作封装在一个工具类里:

package com.Jerry.json;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class Utils {
    public static Student generateStudent()
    {
        Student student = new Student();
        student.setStudentName("Jerry");
        student.setStudentAge(27);
        student.setId(UUID.randomUUID().toString());

        List<Course> courses = new ArrayList<>();
        courses.add(new Course("Math", 99));
        courses.add(new Course("Computer", 100));
        courses.add(new Course("English", 98));

        Dog dog = new Dog();
        dog.setDogName("miumiu");
        dog.setDogAge(1);
        dog.setColor("white");
        dog.setVariety("British Shorthair Cat");

        student.setCourses(courses);
        student.setDog(dog);

        return student;
    }
}

Student对象序列化:

public class FastjsonDemo {
    public static void main(String[] args) {
        Student student = Utils.generateStudent();

        // 序列化
        String str = JSON.toJSONString(student);
        System.out.println(str);
        System.out.println(str.getClass());

        // 反序列化
        Student student1 = JSON.parseObject(str, Student.class);
        System.out.println(student1);
        System.out.println(student1.getClass());
    }
}

结果:

{"courses":[{"courseName":"Math","score":99},{"courseName":"Computer","score":100},{"courseName":"English","score":98}],"dog":{"color":"white","dogAge":1,"dogName":"miumiu","variety":"British Shorthair Cat"},"id":"f707af53-aca8-4ba6-9ef3-852a6d309ece","studentAge":27,"studentName":"Jerry"}
class java.lang.String
Student(studentName=Jerry, studentAge=27, id=f707af53-aca8-4ba6-9ef3-852a6d309ece, courses=[Course(courseName=Math, score=99), Course(courseName=Computer, score=100), Course(courseName=English, score=98)], dog=Dog(dogName=miumiu, dogAge=1, color=white, variety=British Shorthair Cat))
class com.Jerry.json.Student

fastjson好像还有定制序列化和反序列化的api,用到的时候再学。

1.4 注解@``JSONField

fastjson里最重要一个注解就是@JSONField,该注解一般标注在POJO里的属性字段上,下面具体介绍一下该注解的使用。

1.4.1 @JSONField的使用注意

@JSONField的作用对象:

  • Field
  • Setter 和 Getter 方法

但一般还是作用在属性字段Field上,配合name等参数使用。
注意:

  • FastJson 在进行操作时,是根据 getter 和 setter 的方法进行的,并不是依据 Field 进行;
  • 若POJO的属性是私有的,必须有set方法,否则无法反序列化,直接一个@Data注解完事。

    1.4.2 @JSONField的参数

  • name

name参数主要是为了解决json对象的key和JavaBean里的属性字段名不一致的情况,比如json对象里的key是user_id,而POJO里对应的属性字段名称为userId(Java驼峰命名导致这种情况经常出现),为了序列化和反序列化POJO时字段对应的值能被正常解析(否则对应字段的值为null或抛找不到该字段的异常),可以在POJO上这样做:

@Data
public class User {
    @JSONField(name="user_id")
    private String userId;
}

name里是json字符串里的key的字段名称。

  • ordinary

默认 fastjson 序列化一个 java bean,是根据属性字段Field的字母序进行序列化的,可以通过ordinal参数指定序列化时字段的顺序,ordinary参数的值从1开始计数,这个特性需要 1.1.42 以上版本。
上面Student对象序列化时,显示的json字符串里,key的顺序为:course、dog、id、studentAge、studentName,默认是按照key的字母序升序排序,如果想按照如下顺序显示:id、studentAge、dog、studentName、course,可以在POJO里这样做:

@Data
public class Student {
    @JSONField(ordinal = 4)
    private String studentName;

    @JSONField(ordinal = 2)
    private int studentAge;

    @JSONField(ordinal = 1)
    private String id;

    @JSONField(ordinal = 5)
    private List<Course> courses;

    @JSONField(ordinal = 3)
    private Dog dog;
}

结果:

{"id":"ea5498c1-95d7-406d-95af-6bd12969c7ac","studentAge":27,"dog":{"color":"white","dogAge":1,"dogName":"miumiu","variety":"British Shorthair Cat"},"studentName":"Jerry","courses":[{"courseName":"Math","score":99},{"courseName":"Computer","score":100},{"courseName":"English","score":98}]}
  • serialize/deserialize

使用 serialize/deserialize 指定字段不序列化,默认是序列化和反序列化,即serialize=true和deserialize=true,serialize=false表示字段不被序列化,deserialize=false表示字段不被反序列化

@JSONField(serialize=false, deserialize=false)
private Date date;
  • format

使用format配置日期格式化,这个我暂时还没用到,不过body体里有个createTime和deleteTime等字段信息还是会用到的,举个例子:

// 配置date序列化和反序列使用yyyyMMdd日期格式
@JSONField(format="yyyyMMdd")
private Date date;

2、jackson

2.1 简介

Jackson是一个简单的、功能强大的、基于Java的应用库。它可以很方便完成Java对象和Json对象(xml文档or其它格式)进行互转。Jackson社区相对比较活跃,更新速度也比较快。
Jackson库有如下几大特性:

  • 高性能且稳定:低内存占用,对大/小JSON串,大/小对象的解析表现均很优秀 ;
  • 流行度高:是很多流行框架的默认选择 ;
  • 容易使用:提供高层次的API,极大简化了日常使用案例 ;
  • 无需自己手动创建映射:内置了绝大部分序列化时和Java类型的映射关系;
  • 干净的JSON:创建的JSON具有干净、紧凑、体积小等特点 - 无三方依赖:仅依赖于JDK - Spring生态加持:jackson是Spring家族的默认JSON/XML解析器。

上面是我从参考文章中摘录的对jackson的描述,说实话以上几点我在平时工作中体会几乎为0,使用fastjson就是图他的api简单,直接调用静态方法即可;促使我学习和使用jackson的动力是fastjson有漏洞,公司不鼓励用了,这才学习jackson,而且jackson的api使用确实没fastjson简单(api是实例方法,必须先new一个ObjectMapper),但是fastjson的速度快我工作中体会和收益也不大,毕竟这些json库的性能满足日常用还是够的。老外喜欢用jackson,国人喜欢用fastjson。

maven依赖:

<!-- https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-core-asl -->
<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-core-asl</artifactId>
  <version>1.9.13</version>
</dependency>

2.2 数据结构

2.2.1 JsonNode && ObjectNode && ObjectMapper

  • JsonNode

fastjson里将json对象对应一个数据结构:JSONObject,jackson里也设立了一个数据结构对应json对象:JsonNode。jackson里的jsonNode模型是一个树的模型,你可以看到有些api名称,比如createObjectNode都体现了这一点,即把json这个数据结构与树模型对应上,每个json对象对应一个jsonNode(树节点)。JsonNode类是个抽象类,ObjectMapper的方法一般返回的类型都是JsonNode。

  • ObjectNode

上面提到了JsonNode是个抽象类,而ObjectNode是个实体类,JsonNode是不可变的,不能直接对JsonNode进行增删改的操作,可以通过objectMapper.createObjectNode()方法生成一个ObjectNode,在这个ObjectNode上通过objectNode.put(key, value)和objectNode.set(“child1”, childNode)来进行增删改的操作。

  • ObjectMapper

Jackson 在使用之前需要实例化一个 ObjectMapper 对象(它不直接提供全局的默认静态方法),通常我们会将 objectMapper 定义成一个静态成员,或通过 DI 框架注入使用,通过对ObjectMapper对象进行一系列的configure和set方法,所有序列化和反序列化将按照set方法制定的规则进行,具体的一个ObjectMapper的配置如下:

private final static ObjectMapper MAPPER;

static {
    MAPPER = new ObjectMapper()
        // 自动加载 classpath 中所有 Jackson Module
        .findAndRegisterModules()
        // POJO类字段为空或者null是不参加序列化
        .setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 时区序列化为 +08:00 形式
        .configure(SerializationFeature.WRITE_DATES_WITH_ZONE_ID, false)
        // 日期、时间序列化为字符串
        .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
        // 持续时间序列化为字符串
        .configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false)
        // 当出现 Java 类中未知的属性时不报错,而是忽略此 JSON 字段
        .configure(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS, false)
        // 枚举类型调用 `toString` 方法进行序列化
        .configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true)
        // 设置 java.util.Date 类型序列化格式
        .setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
        // 设置 Jackson 使用的时区
        .setTimeZone(SimpleTimeZone.getTimeZone("GMT+8"));
}

2.2.2 api使用

  • 判断JsonNode里是否含有指定的key

    jsonNode.has("id")
    
  • objectNode里添加k-v值

    ObjectNode objectNode = new ObjectNode();
    objectNode.put(key, value);
    

    注意JsonNode是不可变的,不能直接对JsonNode进行增删改的操作,需要用ObjectNode。

  • json字符串转换成jsonNode

    JsonNode rootNode = objectMapper.readTree(jsonStr);
    
  • jsonNode转换成json字符串

    String jsonStr = objectMapper.writeValueAsString(rootNode);
    
  • jsonNode里获得子jsonNode

    JsonNode jsonNode1 = jsonNode.get("courses");
    

    其中jsonNode是父jsonNode,jsonNode1是子jsonNode,get方法里传的参数是父jsonNode里子jsonNode的key字段名称。

  • jsonNode获取对应的value值 ```java // json的value是字符串 String jsonValue = jsonNode.get(key字段名称).asText();

// json的value是int值 int jsonValue = jsonNode.get(key字段名称).asInt();

// json的value是boolean值 boolean jsonValue = jsonNode.get(key字段名称).asBoolean();


- **拷贝一个jsonNode**
```java
ObjectNode newJsonNode = objectMapper.createObjectNode();
newJsonNode.setAll((ObjectNode) oldJsonNode);

注意JsonNode是不可变的,不能直接对JsonNode进行增删改的操作,需要用ObjectNode。

2.3 序列化

jackson序列化有两个api:

  • writeValue(参数,obj):直接将传入的对象序列化为json,并且返回给客户端,其中参数有四种形式:
    • file 将转换后的json字符串保存到指定的file文件中
    • writer 将转换后的json字符串保存到字符输出流中
    • outputStream将转换后的json字符串保存到字节输出流中
    • jsonGenerator类(不常用,不作介绍)
  • writeValueAsString(obj):将传入的对象序列化为json,返回给调用者,这也是jackson里最经常用的序列化方法。

上面两个方法都需要进行异常处理,要么用try-catch子句包围,要么直接往上抛异常。

举例:

public static void main(String[] args) {
        Student student = Utils.generateStudent();
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonStr = "";

        // 序列化
        try {
            jsonStr = objectMapper.writeValueAsString(student);
            System.out.println(jsonStr);
            System.out.println(jsonStr.getClass());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
}

结果:

{"studentName":"Jerry","studentAge":27,"id":"25c41f29-56e2-44d2-94c1-ae829096777b","courses":[{"courseName":"Math","score":99},{"courseName":"Computer","score":100},{"courseName":"English","score":98}],"dog":{"dogName":"miumiu","dogAge":1,"color":"white","variety":"British Shorthair Cat"}}
class java.lang.String

2.4 反序列化

jackson反序列化仅有一个接口:readValue,但readValue方法有很多重载形式,如下:

// 当POJO结构比较简单,直接传POJO.class
public <T> T readValue(String content, Class<T> valueType);

// 当POJO结构比较复杂,用TypeReference<T>
public <T> T readValue(String content, TypeReference<T> valueTypeRef);

// 这个书写起来比较麻烦,就不说明了,不常用,前2个已经彻底满足了
public <T> T readValue(String content, JavaType valueType);

举例:
简单类型的POJO:

@Data
public class User {
    private String userId;
    private String name;
    private int age;
}

复杂类型的POJO见上面的Student实体类。

package com.Jerry.json.jackson;

import com.Jerry.json.Student;
import com.Jerry.json.utils.Utils;
import com.Jerry.json.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Map;


public class JacksonDemo {
    public static void main(String[] args) {
        Student student = Utils.generateStudent();
        ObjectMapper objectMapper = new ObjectMapper();

        // 简单POJO反序列化
        try {
            String jsonStr = "{\"userId\":\"c3bf9543-4137-45a1-8335-135ae8e2a7f6\",\"name\":\"Jerry\",\"age\":27}";
            User user = objectMapper.readValue(jsonStr, User.class);
            System.out.println(user);
            System.out.println(user.getClass());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        // 复杂POJO反序列化
        try {
            String jsonStr = "{\"courses\":[{\"courseName\":\"Math\",\"score\":99},{\"courseName\":\"Computer\",\"score\":100},{\"courseName\":\"English\",\"score\":98}],\"dog\":{\"color\":\"white\",\"dogAge\":1,\"dogName\":\"miumiu\",\"variety\":\"British Shorthair Cat\"},\"id\":\"f707af53-aca8-4ba6-9ef3-852a6d309ece\",\"studentAge\":27,\"studentName\":\"Jerry\"}";
            Map<String, Object> studentMap = objectMapper.readValue(jsonStr, new TypeReference<Map<String,Object>>() {
            });
            System.out.println(studentMap);
            System.out.println(studentMap.getClass());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

结果:

User(userId=c3bf9543-4137-45a1-8335-135ae8e2a7f6, name=Jerry, age=27)
class com.Jerry.json.User
{courses=[{courseName=Math, score=99}, {courseName=Computer, score=100}, {courseName=English, score=98}], dog={color=white, dogAge=1, dogName=miumiu, variety=British Shorthair Cat}, id=f707af53-aca8-4ba6-9ef3-852a6d309ece, studentAge=27, studentName=Jerry}
class java.util.LinkedHashMap

注意:

  • 当POJO是复杂类型时,反序列化时不是直接得到对应的Bean,而是一个Map类型的beanMap,此时readValue方法里的第二个参数是TypeReference,里面一般会是个泛型T。

    2.5 注解

    jackson里的注解有很多,这里介绍一下常用的注解。

  • **@JsonProperty**

该注解标注在属性字段上,用来处理json对象里的key和POJO里的属性名称不一致的情况,与fastjson里的@JSONField一个用处。该注解有几个参数:

  • value:属性字段和json里的key的映射关系,代表属性字段对应的json里的key,对应fastjson里的name;
  • index:对应fastjson里的ordinary?(不是)
  • defaultValue:默认值?
    • **@JsonIgnore**

该注解用来标注在属性字段上,用来表示该属性不参与序列化,举例:

@JsonIgnore
@JsonProperty("userName")
private String name;
  • **@JsonIgnoreProperties**

该注解用来标注在POJO类上,用来表示该POJO类里哪些字段不参与序列化,举例:

@Data
@JsonIgnoreProperties(value={"name","userAge"})
public class Person {
    @JsonIgnore
    @JsonProperty("userName")
    private String name;
    @JsonProperty("userAge")
    private Integer age;
    @JsonProperty("userHeight")
    private Integer height;
}

@JsonProperty注解好像在反序列化时没有发挥作用,在实际使用时发现的!应该是我使用姿势不对~~~

2.6 jackson工具类

上面的介绍可以看出,jackson的api使用就是没fastjson方便,fastjson直接用静态方法就可以了,而jackson还需要new一个ObjectMapper,反序列化复杂类型的对象时还不能直接得到JavaBean,而是一个Map类型的beanMap,而且ObjectMapper对象可能需要一些复杂的设置(通过configure方法完成),因此项目里使用jackson作为json库时,一般会封装一个Utils,Utils里提供静态方法供外部使用,这里参考链接里的utils,如下:
JacksonUtils:

package com.Jerry.json.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import java.text.SimpleDateFormat;
import java.util.SimpleTimeZone;

public class JacksonUtils {
    private final static ObjectMapper MAPPER;

    static {
        MAPPER = new ObjectMapper()
                // 自动加载 classpath 中所有 Jackson Module
                .findAndRegisterModules()
                // 时区序列化为 +08:00 形式
                .configure(SerializationFeature.WRITE_DATES_WITH_ZONE_ID, false)
                // 日期、时间序列化为字符串
                .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
                // 持续时间序列化为字符串
                .configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false)
                // 当出现 Java 类中未知的属性时不报错,而是忽略此 JSON 字段
                .configure(SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS, false)
                // 枚举类型调用 `toString` 方法进行序列化
                .configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true)
                // 设置 java.util.Date 类型序列化格式
                .setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
                // 设置 Jackson 使用的时区
                .setTimeZone(SimpleTimeZone.getTimeZone("GMT+8"))
                // POJO类字段为空或者null是不参加序列化
                .setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    public static String serialize(Object obj) {
        try {
            return MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T deserialize(String jsonText, TypeReference<T> type) {
        try {
            return MAPPER.readValue(jsonText, type);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T deserialize(String jsonText, Class<T> beanClass) {
        try {
            return MAPPER.readValue(jsonText, beanClass);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static JsonNode deserialize(String jsonText) {
        try {
            return MAPPER.readTree(jsonText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

3、总结

还是fastjson香啊!

参考:

Fastjson 等等,四种 Java 常用 JSON 库性能比较
fastjson到底做错了什么?为什么会被频繁爆出漏洞?
fastjson的JSONArray和JSONObject
Fastjson 简明教程
初识Jackson — 世界上最好的JSON库
Fastjson到了说再见的时候了
Jackson序列化和反序列化
Jackson objectMapper.readValue 方法 详解
Jackson JsonNode
JSON 之 Jackson