You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson序列化时属性名定义冲突问题求助

问题与解决方案

问题详情

我有一个AusgangsrechnungGeneral类,包含属性abrechnungsmonat。此前通过Jackson从JSON反序列化时,JSON中的abrechnungsMonat能正常映射到该属性。现在需要实现:

  • 反序列化:JSON的abrechnungsMonat映射到类的abrechnungsmonat属性
  • 序列化:输出JSON的属性名为abrechnungsmonat

编写的代码片段如下:

@JsonFormat(pattern="yyyy-MM")
@JsonDeserialize(using = YearMonthDeserializer.class)
@JsonSetter("abrechnungsMonat")
private YearMonth abrechnungsmonat;

@JsonGetter("abrechnungsmonat")
public YearMonth getAbrechnungsmonat() {
    return this.abrechnungsmonat;
}

该方式对其他属性有效,但此处抛出错误:

java.lang.IllegalStateException: Conflicting/ambiguous property name definitions (implicit name 'abrechnungsmonat'): found multiple explicit names: [abrechnungsmonat, abrechnungsMonat], but also implicit accessor: [field com.itf.ghost.propartsyncservice.api.rechnung.propartmodel.AusgangsrechnungGeneral#abrechnungsmonat][visible=true,ignore=false,explicitName=false]

使用了Lombok的@Data注解,手动定义了getter,按理解Lombok不会额外生成。完整类代码:

@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString(callSuper = true)
@SuperBuilder
@JsonIgnoreProperties(ignoreUnknown = true)
public class AusgangsrechnungGeneral extends Rechnung {

    @JsonSetter("leistungsZeitraum")
    private String leistungszeitraum;

    @JsonGetter("leistungszeitraum")
    public String getLeistugnszeitraum() {
        return this.leistungszeitraum;
    }

    private String filePath;

    private Boolean isProberechnung;

    @JsonFormat(pattern="yyyy-MM-dd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    private LocalDate bezahltAm;

    @JsonFormat(pattern="yyyy-MM-dd")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    private LocalDate zahlungErwartetAm;

    @JsonFormat(pattern="yyyy-MM")
    @JsonDeserialize(using = YearMonthDeserializer.class)
    @JsonSetter("abrechnungsMonat")
    private YearMonth abrechnungsmonat;

    @JsonGetter("abrechnungsmonat")
    public YearMonth getAbrechnungsmonat() {
        return this.abrechnungsmonat;
    }

    @JsonSetter("kundenId")
    private Long kunde;

    @JsonGetter("kunde")
    public Long getKunde() {
        return this.kunde;
    }

    @JsonSetter("abls")
    private List<AbrechenbareLeistung> abrechenbareLeistungen;

    @JsonGetter("abrechenbareLeistungen")
    public List<AbrechenbareLeistung> getAbrechenbareLeistungen() {
        return this.abrechenbareLeistungen;
    }
}

错误原因

Jackson同时识别到了三个属性名来源:

  1. 字段本身的隐式属性名abrechnungsmonat
  2. @JsonSetter指定的abrechnungsMonat
  3. @JsonGetter指定的abrechnungsmonat

三者冲突导致抛出IllegalStateException。即使手动定义了getter,Lombok的@Data包含@Getter注解,加上Jackson的自动字段检测机制,依然会触发冲突。

解决方案

方案1:使用@JsonAlias指定反序列化别名(推荐)

@JsonAlias专门用于定义反序列化时可匹配的别名,序列化时仍使用字段名输出,无需手动编写@JsonGetter/@JsonSetter,避免冲突:

@JsonFormat(pattern="yyyy-MM")
@JsonDeserialize(using = YearMonthDeserializer.class)
@JsonAlias("abrechnungsMonat") // 反序列化接受该别名
private YearMonth abrechnungsmonat;

方案2:使用@JsonProperty统一配置

通过@JsonProperty同时控制序列化和反序列化的属性名,结合access参数明确读写规则:

@JsonFormat(pattern="yyyy-MM")
@JsonDeserialize(using = YearMonthDeserializer.class)
@JsonProperty(value = "abrechnungsmonat", access = JsonProperty.Access.READ_WRITE)
@JsonProperty("abrechnungsMonat") // 反序列化匹配该名称
private YearMonth abrechnungsmonat;

方案3:禁用Jackson字段自动检测

在类上添加@JsonAutoDetect,关闭字段的自动识别,仅通过getter/setter处理属性:

@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString(callSuper = true)
@SuperBuilder
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE) // 关闭字段自动检测
public class AusgangsrechnungGeneral extends Rechnung {
    // 原有代码不变
}

内容的提问来源于stack exchange,提问作者Tobias Walter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:55:22