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

Spring Boot中Jackson序列化XML同名子元素列表引发异常

Spring Boot Jackson XML序列化:列表子元素同名导致Getter冲突解决方案

问题场景

在Spring Boot 3.3.5 + jackson-dataformat-xml v2.18.2环境下,PlayerActivityDto中的startingBalanceList和endingBalanceList两个列表,需要将子元素统一序列化为<summaryBalance>标签,但Jackson抛出InvalidDefinitionException,提示getter方法冲突。

异常信息:

Failed to evaluate Jackson serialization for type [class PlayerActivityDto]: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Conflicting getter definitions for property "summaryBalance": PlayerActivityDto#getStartingBalanceList() vs PlayerActivityDto#getEndingBalanceList()

问题原因

两个列表字段均使用@JacksonXmlProperty(localName = "summaryBalance"),Jackson会将该注解的localName作为内部属性键,导致两个字段被识别为同一个属性,对应的getter方法因此产生冲突。

解决方案

提供三种可行方案,按需选择:

方案1:为列表字段指定唯一JSON属性名

通过@JsonProperty为每个列表指定唯一的内部属性名,同时保留XML子元素的名称配置:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.util.List;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Builder
public class PlayerActivityDto {
    @JacksonXmlProperty(localName = "playerActivityId", isAttribute = true)
    private String brandId;

    @JacksonXmlProperty(localName = "player")
    private PlayerDto player;

    @JacksonXmlProperty(localName = "playerActivityDetail")
    private PlayerActivityDetailDto playerActivityDetail;

    @Setter
    @Getter
    @JsonProperty("startingBalanceList")
    @JacksonXmlElementWrapper(localName = "startingBalanceList")
    @JacksonXmlProperty(localName = "summaryBalance")
    private List<SummaryBalanceDto> startingBalanceList;

    @Getter
    @Setter
    @JsonProperty("endingBalanceList")
    @JacksonXmlElementWrapper(localName = "endingBalanceList")
    @JacksonXmlProperty(localName = "summaryBalance")
    private List<SummaryBalanceDto> endingBalanceList;

    @JacksonXmlProperty(localName = "playerMovement")
    @JacksonXmlElementWrapper(localName = "playerMovementList")
    private List<FundsMovementDto> playerMovementList;
}

方案2:在子元素DTO上配置XML根元素名称

在SummaryBalanceDto类上添加@JacksonXmlRootElement指定子元素标签名,移除列表字段上的@JacksonXmlProperty:

// SummaryBalanceDto.java
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

@JacksonXmlRootElement(localName = "summaryBalance")
public class SummaryBalanceDto {
    // 类字段及注解
}

// PlayerActivityDto.java中修改列表字段
@Setter
@Getter
@JacksonXmlElementWrapper(localName = "startingBalanceList")
private List<SummaryBalanceDto> startingBalanceList;

@Getter
@Setter
@JacksonXmlElementWrapper(localName = "endingBalanceList")
private List<SummaryBalanceDto> endingBalanceList;

方案3:为Getter方法指定唯一属性名

利用Lombok的onMethod_参数,为自动生成的getter添加@JsonGetter,明确属性名:

import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import java.util.List;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Builder
public class PlayerActivityDto {
    @JacksonXmlProperty(localName = "playerActivityId", isAttribute = true)
    private String brandId;

    @JacksonXmlProperty(localName = "player")
    private PlayerDto player;

    @JacksonXmlProperty(localName = "playerActivityDetail")
    private PlayerActivityDetailDto playerActivityDetail;

    @Getter(onMethod_ = {@JsonGetter("startingBalanceList")})
    @Setter
    @JacksonXmlElementWrapper(localName = "startingBalanceList")
    @JacksonXmlProperty(localName = "summaryBalance")
    private List<SummaryBalanceDto> startingBalanceList;

    @Getter(onMethod_ = {@JsonGetter("endingBalanceList")})
    @Setter
    @JacksonXmlElementWrapper(localName = "endingBalanceList")
    @JacksonXmlProperty(localName = "summaryBalance")
    private List<SummaryBalanceDto> endingBalanceList;

    @JacksonXmlProperty(localName = "playerMovement")
    @JacksonXmlElementWrapper(localName = "playerMovementList")
    private List<FundsMovementDto> playerMovementList;
}

效果验证

上述方案均可实现:

  • 列表外层标签分别为<startingBalanceList>和<endingBalanceList>
  • 列表内的子元素统一为<summaryBalance>
  • 解决Jackson的getter冲突异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:49:51