ObjectMapper反序列化时@JsonIgnore字段带默认值问题求解
问题根因
你遇到的id=0和Jackson反序列化逻辑无关,是Java基本类型的语言特性导致的:
@JsonIgnore注解生效后,Jackson在序列化、反序列化两个阶段都会完全忽略id字段,根本不会对这个字段做任何赋值操作。int是基本数据类型,JVM实例化User对象时,会自动给int类型的字段赋予默认值0,这个值是对象创建时自带的初始值,不是反序列化时写入的。- 基本类型
int只能表示数值,无法表示“字段未赋值”的状态,只要字段类型是int,它永远会有一个默认值0。
你期望的User(name=Bob)输出,本质是要让id字段保持未赋值状态,同时toString()方法不打印该字段。
可行解决方案
方案1:改动最小,直接适配需求
- 把id字段的类型从基本类型
int改为包装类型Integer:Integer是引用类型,对象实例化时默认值为null,可以准确表示“未赋值”的状态。 - (可选)如果希望Lombok生成的toString()方法不打印id字段,给id字段加上
@ToString.Exclude注解即可。
修改后的User类代码如下:
@Data class User { @JsonIgnore @ToString.Exclude // 加了之后打印对象时不会输出id字段 private Integer id; private String name; }
不需要修改任何序列化、反序列化的业务代码,直接运行原有测试逻辑,就能得到你期望的输出:
==>String Value: { "name" : "Bob" } ===>Object Value: User(name=Bob)
方案2:更严谨的字段权限控制
如果你的业务需要防止恶意构造的JSON传入id字段覆盖值(@JsonIgnore本身已经能挡住这个场景),可以保留@JsonIgnore注解不用改动,额外给ObjectMapper配置严格的未知字段校验即可,不需要修改类结构:
ObjectMapper mapper = new ObjectMapper(); // 反序列化时遇到类里不存在/被忽略的字段直接抛错,避免非法字段注入 mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
这个配置适合对参数安全性要求高的场景,普通业务场景用方案1就足够。
注:Java是静态强类型语言,只要User类里定义了id字段,实例化后的对象就一定存在这个结构,不存在“对象不包含id字段”的效果,你看到的输出差异只是字段值和打印规则的区别。
内容的提问来源于stack exchange,提问作者Shivangi Gupta
相关产品推荐
相关产品推荐

