fastJson和jackJson的使用和区别

文章讨论了在Java中使用fastJson和jackJson进行反序列化时遇到的不同情况,包括正常字段、额外字段、大小写不一致和数字类型包装类的情况。fastJson在处理额外字段和大小写时更加灵活,而jackJson需要特定配置才能忽略大小写。在处理数字类型为包装类时,由于默认初始值不同,结果会有细微差别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


首先给出我定义的对象类:

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Student implements Serializable {
    private long id;
    private String name;
    private int age;
    private String sex;

情况1:现在我有一个正常的序列化后的字符串(note:序列化字段均为java对象中的字段),需要将其反序列化为一个对象。

fastJson和jackJson的做法如下:

String json = "{\"name\": \"king\",\n"
                        + "\"age\": 1,\n"
                        + "\"sex\":\"1\"\n }";

Student student_jackJson = new ObjectMapper().readValue(json, Student.class);
Student student_fastJson = JSONObject.toJavaObject(JSONObject.parseObject(json), Student.class);

System.out.println("student_jackJson = " + student_jackJson);
System.out.println("student_fastJson = " + student_fastJson);

结果如下:
在这里插入图片描述

分析:可以发现对于该情况,fastJson和jackJson均会输出同样的结果。两者使用无异

情况2:当现在我有一个不正常的序列化后的字符串(note:存在序列化字段不在java对象字段中),需要将其反序列化为一个对象。

String json = "{\"name\": \"king\",\n"
                        + "\"age\": 1,\n"
                        + "\"color\": \"red\",\n"
                        + "\"sex\":\"1\"\n }";
Student student_fastJson = JSONObject.toJavaObject(JSONObject.parseObject(json), Student.class);
Student student_jackJson = new ObjectMapper().readValue(json, Student.class);

System.out.println("student_jackJson = " + student_jackJson);
System.out.println("student_fastJson = " + student_fastJson);

结果:(报错)
在这里插入图片描述

分析:从报错信息来看,是jackJson解析错误,为了让大家看的更清楚和通透,下面我将每个反序列化的步骤try…catch一下,再跑一遍。

使用try…catch重试:

String json = "{\"name\": \"king\",\n"
                        + "\"age\": 1,\n"
                        + "\"color\": \"red\",\n"
                        + "\"sex\":\"1\"\n }";
try {
      Student student_fastJson = JSONObject.toJavaObject(JSONObject.parseObject(json), Student.class);
      System.out.println("student_fastJson = " + student_fastJson);
} catch (Exception e) {
      System.out.println("student_fastJson解析报错" + e);
}
try {
      Student student_jackJson = new ObjectMapper().readValue(json, Student.class);
      System.out.println("student_jackJson = " + student_jackJson);
} catch (Exception e) {
      System.out.println("student_jackJson解析报错" + e);
}

结果如下图所示:可以看到fastJson输出了;但是jackJson报错了,不能识别color字段,没有标记为可忽略的
在这里插入图片描述

分析:jackJson不支持不存在的字段进行对象的反序列化,fastJson则会过滤掉该情况
解决:在java对象中写上注解@JsonIgnoreProperties(ignoreUnknown = true)即可

情况3:当现在我有一个不正常的序列化后的字符串(note:序列化字段在java对象字段中,但是大小写不一样),需要将其反序列化为一个对象。

String json = "{\"name\": \"king\",\n"
                        + "\"Age\": 1,\n"
                        + "\"color\": \"red\",\n"
                        + "\"Sex\":\"1\"\n }";
try {
       Student student_fastJson = JSONObject.toJavaObject(JSONObject.parseObject(json), Student.class);
       System.out.println("student_fastJson = " + student_fastJson);
} catch (Exception e) {
       System.out.println("student_fastJson解析报错" + e);
}
try {
       Student student_jackJson = new ObjectMapper().readValue(json, Student.class);
       System.out.println("student_jackJson = " + student_jackJson);
} catch (Exception e) {
       System.out.println("student_jackJson解析报错" + e);
}

结果如下图所示:可以看到fastJson可以忽略大小写问题正常解析字段参数,而jackJson因大小写问题“age”和“sex”字段无法正常解析。
在这里插入图片描述
分析:fastJson会把大写转小写,而jackJson解析时时默认匹配大小写的。
源码分析如下:
fastJson:
核心方法是smartMatch。里面有两个重要的转换:fnv1a_64_lower、fnv1a_64_extract。
如果fnv1a_64_lower中得到的hashcode值不在对象生成的smartMatchHashArray中,再执行fnv1a_64_extract,判断所得的hashCode值是否在对象的smartMatchHashArray中。当找到值后,即可进行赋值操作。
在这里插入图片描述

fnv1a_64_lower:将大写转成小写
fnv1a_64_extract:将字段中的下划线和减号去掉,然后转成小写

在这里插入图片描述
jackJson:
核心方法是vanillaDeserialize,在该方法里会将传入序列化后的字段逐个遍历,并通过SettableBeanProperty prop = this._beanProperties.find(propName)去拿到字段的值。在下图中可以看到,jackJson默认不转换大小写。
在这里插入图片描述
jackJson忽略大小写的解决方式:设置忽略大小写

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,true);//忽略大小写 默认为false
Student student_jackJson = objectMapper.readValue(json, Student.class);
System.out.println("student_jackJson = " + student_jackJson);

在这里插入图片描述

情况4:在情况3的条件下,将Student类的数字类型参数改为包装类

即:当现在我有一个不正常的序列化后的字符串(note:序列化字段在java对象字段中,但是大小写不一样),需要将其反序列化为一个对象。此时Student类为:

public class Student {
    private Long id;
    private String name;
    private Integer age;
    private String sex;
}

此时执行代码:

```java
String json = "{\"name\": \"king\",\n"
                        + "\"Age\": 1,\n"
                        + "\"color\": \"red\",\n"
                        + "\"Sex\":\"1\"\n }";
try {
       Student student_fastJson = JSONObject.toJavaObject(JSONObject.parseObject(json), Student.class);
       System.out.println("student_fastJson = " + student_fastJson);
} catch (Exception e) {
       System.out.println("student_fastJson解析报错" + e);
}
try {
       Student student_jackJson = new ObjectMapper().readValue(json, Student.class);
       System.out.println("student_jackJson = " + student_jackJson);
} catch (Exception e) {
       System.out.println("student_jackJson解析报错" + e);
}

结果:
在这里插入图片描述
分析:因为数字包装类型的初始化值是null,而基本数据类型是0,因此有细微的差距。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值