SpringMvc 与 Lombok 中 JSON 反序列化失败
错误复现_1
@Data
public class User{
private Long id;
private boolean isOk;
}
@RequestMapping
public R<User> getUser(@RequestBody User user){
return R.success(user);
}
// 前端传参 - {"id": 123456789,"isOk": true}
// 后端返回 - {"id": 123456789,"isOk": false}
排查分析_1
查看 User 类 class 文件。
public class User{ pirvate Long id; private boolean isOk; public User() {} public Long getId() { return this.id; } public boolean isOk() { return this.isOk; } public void setId(final Long id) { this.id = id; } public void setOk(final boolean isOk) { this.isOk = isOk; } }
提出猜测:Lombok 对于 boolean 类型生成的 Getter/Setter 方法与其他类型不同,该原因导致的数据不一致。
错误复现_2
@Data
public class User{
private Long id;
private String Name;
private Long cId;
}
// 前端传参 - {"id": 1,"Name": "LXL","cId": 2}
@RequestMapping
public void getUser(@RequestBody User user){
System.out.println(user.getId()); // 1
System.out.println(user.getName()); // null
System.out.println(user.getCId()); // null
}
排查分析_2
查看 User 类 class 文件。
public class User { private Long id; private String Name; private Long cId; public User() {} public Long getId() { return this.id; } public String getName() { return this.Name; } public Long getCId() { return this.cId; } public void setId(final Long id) { this.id = id; } public void setName(final String Name) { this.Name = Name; } public void setCId(final Long cId) { this.cId = cId; } }
提出猜测:反序列化时,由于某种原因导致无法正常赋值。
揭开谜团
结合上述两个猜测,去了解了 SpringMvc 的反序列化机制、Lombok 的代码生成机制。
先说一下 SpringMvc 的 @RequestBody 注解:
- SpringMvc 中通过 @RequestBody 注解实现将 json 数据转成 java 对象。
- 处理 @RequestBody 注解时,内部使用 jackson 框架完成该反序列化过程。
接下来是 Jackson 框架的反序列化操作步骤:
- 仅有全参数构造器时,通过调用该构造器,映射 JSON 属性与 Construction 参数列表完成对象的实例化。
- 有无参数构造器时,优先使用无参数构造器 + Getter/Setter 方法完成序列化与反序列化。调用反序列化的目标类的无参构造函数,构造一个 java 对象。然后调用该类的成员变量的 set 方法,为该对象的每一个成员变量赋值。
- Jackson 遵守了
JavaBean
的规范:
- 首字母为大写的属性名(如:Name, URL, SuV…),这种属性名直接忽略不注入。
- 第一个字母是小写,第二个字母大写的情况(如:pId, sUV…),在生成 Getter/Setter 的时,直接在前面加上 set/get,比如 pId 生成 setpId()/getpId(),所以 pId 属性在注入的时候会寻找 setpId() 方法,而不是 setPId() 。
最后是 Lombok 的 Getter/Setter 生成机制:文章来源:https://www.toymoban.com/news/detail-701060.html
- 当成员变量为 boolean 类型时,属性名为 isXxx 生成的 Getter/Setter 方法的方法名为 isXxx/setXxx。
- 其他基本类型与所有引用数据类型,属性名为 aaBb 生成的 Getter/Setter 方法的方法名为 getAaBb/setAaBb,例如 isXxx 生成 getIsXxx/SetIsXxx。
这几个知识点就可以解决错误 1、错误 2 啦!!!文章来源地址https://www.toymoban.com/news/detail-701060.html
- 错误 1 造成原因:为属性名 isOk 查找 Setter 方法时,找不到 setIsOk,所以无法注入,使用默认值 false。
- 错误 2 造成原因:属性名 Name 不符合 JavaBean 规范被直接忽略注入;属性名 cId 查找的 Setter 方法名应该为 setcId,而 Lombok 生成的是 setCId,也是注入不了的。
方案与总结
- 规范且合理制定成员变量名称。
- 尽量使用包装类,既可以符合 Java 语言面向对象的特性,同时可以避免 Lombok 生成的 Setter/Getter 与 Jackson 框架规则间的冲突。
- 上述两种方案不适合的话,可以考虑手动生成 Setter/Getter 方法。
- 通过 @JsonProperty 显式指定 JSON 属性与 Java 属性的对应关系。
到了这里,关于SpringMvc 与 Lombok 碰撞导致 JSON 反序列化失败的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!