具有短名称的字段的默认 Jackson 命名策略

default Jackson naming strategy for fields with short names

我使用 Jackson 很多年了,我不确定我是否遇到过这个问题。

在 Spring Boot 2.5.5 项目中使用 Jackson 2.12.5,我有一个需要序列化的对象。我对其他领域没有问题,但是这两个领域给我带来了问题:

@Jacksonized
@Builder
@Getter
public class ComputationResult {
  
  private final String pId;

  private final String cId;

  ... other fields ignored

} 

如您所见,我也在使用 Lombok 注释。当“delombokized”时,吸气剂是:

  public String getPId() {
    return this.pId;
  }

  public String getCId() {
    return this.cId;
  }

序列化 POJO 时,我希望字段名称为“pId”和“cId”,但它们不是:我得到“pid”和“cid”,均为小写。我对其他领域没有问题,尊重案例。

这给我带来了一个问题,因为我需要序列化然后反序列化 POJO,反序列化失败是因为它无法将“cid”json 字段映射到“cId”java 字段。

有多种解决方法(我在现场使用 @JsonAlias("cid") 以允许反序列化),但我很困惑:这是杰克逊的预期行为吗?它会根据长度对字符串字段进行不同的处理吗?还是我不知道的 java beans 约定?

是否可以在 objectMapper 中设置 属性 来“修复”该行为,而无需实现我自己的 com.fasterxml.jackson.databind.PropertyNamingStrategy

问题似乎是由 属性 名称开头只有一个小写字符时 JavaBeans 方法如何生成引起的。你可能会对 getpId and getcId are indeed correctly named 和我一样感到惊讶。

简而言之,pId 正确地导致了 getter getpId 而不是 Lombok 生成的 getPId (我认为应该保留一个 JavaBeans) .

现在,有趣的是 Jackson 出于某种原因分别从 getCIdgetPId 中制作了 cidpid...同时为 getcIdgetpId.

生成 cIdpId

因此,虽然 getcIdgetpId 是 JavaBeans 的一个怪癖,但当 getter 被正确命名时,Jackson 似乎默认行为正确,即 getpId -> "pId"getcId -> "cId"
鉴于 Lombok 生成 getPIdgetCId,这导致结果 JSON 中的全小写键,反序列化不起作用。

如果您不喜欢 getpId/getcId 命名,那么您可能必须编写自己的 getter 并明确强制使用 属性 名称:

@Builder
@Jacksonized
class ComputationResult {

    private final String pId;
    private final String cId;

    @JsonProperty("pId")
    public String getPId() {
        return pId;
    }

    @JsonProperty("cId")
    public String getCId() {
        return cId;
    }
}

对于二传手,由于 final 字段,您已经不得不依赖 @Jacksonized,所以这没有什么区别。请注意,必须省略 @Getter,因为它会导致重复的属性(使用另一种命名方式)。