最近遇到一个很新奇的问题,之前从来没遇到过,用apifox测试的时候,传参但是在打断点的时候发现没有赋值成功。

[{
  "cityCode": "xxx",
  "cityName": "xx市",
  "deptCode": "xxx",
  "deptName": "xx部",
  "cAdminName": "刘xx",
  "cAdminAccount": "xxx",
  "sAdminName": "xxx",
  "sAdminAccount": "xxx"
}]
// 上面是我postman请求参数

   
    // 这是我实体表的一部分代码(ps:实体类加的是@Data 注解)
    private String cAdminName;

    private String cAdminAccount;

    private String sAdminName;

    private String sAdminAccount;

    private String cityCode;

    private String cityName;

    private String deptCode;

    private String deptName;

但是打断点测试的时候,只有cityCode,cityName,deptCode,deptName这几个属性成功赋值了,剩下的都是空的!

经过一顿排查发现,这是由于 Java Bean 的命名规范 和JSON序列化库(如 Jackson)如何处理这些名称之间的不匹配所导致的。

简单来说,问题出在属性命名上。

问题的原因

JSON 库(例如 Spring Boot 默认的 Jackson)在将 JSON 字符串转换为 Java 对象时,需要依赖标准的 getter/setter 方法。

  1. 对于正常工作的字段:
  • 一个名为 cityCode 的属性,按照 Java Bean 规范,它的 setter 方法是 setCityCode()。
  • Jackson 看到 JSON 中的 "cityCode" 键,会正确地寻找并调用 setCityCode() 方法,因此赋值成功。deptName、cityName 等都是同理。
  1. 对于不工作的字段:
  • 一个名为 cAdminName 的属性,按照 Java Bean 规范,它的 setter 方法应该是 setcAdminName() (请注意,c 是小写的)。
  • 这是一个非常容易混淆的规范点。当属性名的第二个字母是大写时(如 cAdminName),第一个字母在 setter 方法名中保持小写。
  • 然而,很多工具或开发者可能会误解这个规范,或者 Jackson 的某些版本/配置可能对此有不同的处理方式,它可能会错误地去寻找一个名为 setCAdminName()(大写 C)的方法。
  • 当 Jackson 看到 JSON 中的 "cAdminName" 时,它试图找到一个合适的 setter 方法来给 cAdminName 属性赋值。因为它找不到一个完全匹配的、符合其内部规则的 setter(无论是 setcAdminName还是 setCAdminName 可能都不符合它此刻的查找逻辑),所以它只能静默地跳过这个字段的赋值。
  • cAdminAccount、sAdminName 和 sAdminAccount 这几个字段都存在同样的问题,因为它们都遵循 xAbc... 这种命名模式。

核心结论: 失败的根本原因在于,对于 cAdminName 这类名称,序列化框架无法找到它期望的 setter 方法,因此放弃了对这些字段的赋值。

如何解决

有几种方法可以解决这个问题:

  1. 重命名属性:这是最清晰、最一劳永逸的办法。将 Java 实体类中的属性名改得不那么模棱两可。
  • cAdminName -> cityAdminName
  • sAdminName -> provinceAdminName
  • 这样,setter 方法就会变成无歧义的 setCityAdminName(),JSON 键也相应地变成 "cityAdminName"。这完全消除了命名规范带来的困惑。
  1. 使用 @JsonProperty 注解(推荐的“修复”方案):如果您不想或不能修改属性名,可以使用此注解来明确地告诉 Jackson JSON 键和 Java 属性之间的映射关系。
    import com.fasterxml.jackson.annotation.JsonProperty;

    @JsonProperty("cAdminName")
    private String cAdminName;

这个注解会强制 Jackson 将 JSON 中的 cAdminName 键映射到这个字段,无论 setter 方法的命名是什么,通常能直接解决问题。

    2. 手动编写 Setter:如果类没有使用 Lombok,可以为这几个有问题的字段手动编写标准的 setter 方法,确保命名正确(例如 public void setcAdminName(...))。如果正在使用 Lombok,这个方法就不太合适了。

综上所述,这个遇到的情况是一个很常见的 Java/JSON 映射问题,根源在于 cAdminName 这种命名方式的模糊性。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐