Jackson:如何反序列化经findTypedValueSerializer()序列化的对象?
嘿,我来帮你捋清楚这个问题!序列化成功但反序列化抛出空指针,大概率是反序列化逻辑里没处理好对象初始化、null值或者字段映射的问题,咱们一步步排查:
1. 先确认对象是否被正确初始化
空指针最常见的原因就是你在调用对象方法前,没有创建实例。比如在deserialize方法里,直接去给一个未初始化的对象赋值,肯定会炸。
举个错误示例:
public class UserDeserializer extends JsonDeserializer<User> { @Override public User deserialize(JsonParser parser, DeserializationContext context) throws IOException { User user = null; // 这里没初始化! while (parser.nextToken() != JsonToken.END_OBJECT) { if ("username".equals(parser.getCurrentName())) { parser.nextToken(); user.setUsername(parser.getText()); // 空指针触发点 } } return user; } }
解决办法:在处理字段前先创建对象实例,比如User user = new User();,如果类没有无参构造,就用带参构造或者通过反射实例化。
2. 核对JSON字段与类字段的映射一致性
你序列化时可能用了注解(比如@JsonProperty指定别名)调整了字段名,但反序列化时没对应上,导致某个必要字段没被赋值,后续调用该字段的方法就会空指针。
比如序列化时你把类里的userName映射为JSON里的uname,但反序列化时还是读userName键,结果拿到null值,调用userName.trim()就炸了。
解决办法:
- 检查类上的
@JsonProperty注解,确保序列化和反序列化的字段别名一致; - 在
deserialize方法里读取字段时,用JSON实际的键名,而不是类字段名。
3. 处理JSON中的null值或缺失字段
如果JSON里某个字段是null,或者根本不存在,而你直接拿这个值去调用方法(比如String str = parser.getText(); str.trim()),就会触发空指针。另外,如果类字段是基本类型(比如int),但JSON里对应字段是null,有些序列化库会抛出异常,间接导致空指针。
解决办法:
- 读取字段前先判断是否为null:
parser.nextToken(); String name = parser.getText(); if (name != null) { user.setName(name.trim()); } - 对于可选字段,先检查JSON中是否存在该键,再进行赋值操作;
- 基本类型尽量用包装类(比如
Integer代替int),避免null转基本类型的异常。
4. 加调试跟踪,定位具体触发点
空指针的根源往往藏在细节里,直接加日志或断点是最有效的办法:
- 在
deserialize方法里打印当前解析的token和字段值:System.out.println("当前Token: " + parser.getCurrentToken()); System.out.println("字段名: " + parser.getCurrentName()); - 用IDE断点逐行跟踪,看哪一行的变量是null,以及为什么会是null。
5. 检查注解的正确性
确保类上的反序列化注解没有写错:
- 确认
@JsonDeserialize(using = YourDeserializer.class)正确标注到了目标类上; - 如果用了
@JsonIgnore或其他过滤注解,要确保反序列化时这些字段的处理符合预期(比如不要试图读取被忽略的字段)。
如果按照上面的步骤还是没解决,可以把你的JsonDeserializer核心代码和对应的类结构贴出来,这样能更精准定位问题。
内容的提问来源于stack exchange,提问作者Geoffrey De Smet

