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

Java抽象类Map的Jackson序列化问题:无法生成目标JSON格式

问题描述

目标API要求的请求JSON格式:

{
  "firstName" : "XYZ",
  "family" : {
     "commonDetails" : {
         "secondName" : "ABC"
     }, 
     "1" : "Mother name",
     "2" : "Father name",
     "3" : "Spouse name"
  }
}

我定义的Java请求类如下:

UserDetails类

public class UserDetails {
   private String firstName;
   private Map<String, AbstractFamilyDetails> details;
}

AbstractFamilyDetails抽象类

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties("type")
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.EXISTING_PROPERTY,
        property = "type"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = FamilyCommonDetails.class, name = "COMMON_DETAILS"),
        @JsonSubTypes.Type(value = FamilyIndividual.class, name = "FAMILY")
})
public abstract class AbstractFamilyDetails {
    private String type;
}

FamilyCommonDetails子类

@Data
@EqualsAndHashCode(callSuper = true)
public class FamilyCommonDetails extends AbstractFamilyDetails {
    private String secondName;

    @Builder
    public FamilyCommonDetails(String secondName) {
        super("COMMON_DETAILS");
        this.secondName = secondName;
    }

    public FamilyCommonDetails() {
        super("COMMON_DETAILS");
    }

    @Override
    public String toString() {
        return this.secondName;
    }
}

FamilyIndividual子类

@Data
@EqualsAndHashCode(callSuper = true)
public class FamilyIndividual extends AbstractFamilyDetails {
    private String individual;

    @Builder
    public FamilyIndividual(String individual) {
        super("FAMILY");
        this.individual = individual;
    }

    public FamilyIndividual() {
        super("FAMILY");
    }

    @Override
    public String toString() {
        return this.individual;
    }
}

但实际发送给服务器的JSON是:

{
  "firstName" : "XYZ",
  "family" : {
     "commonDetails" : {
         "secondName" : "ABC",
     }, 
     "1" : {"individual": "Mother name"},
     "2" : {"individual": "Father name"},
     "3" : {"individual": "Spouse name"}
  }
}

请问哪里出错了?是否需要自定义Jackson序列化器实现需求?


解决方案

问题根源

  1. FamilyIndividual序列化方式不符合要求:Jackson默认会把对象序列化为键值对结构,所以你的FamilyIndividual实例被转成了{"individual": "xxx"}的嵌套对象,但API需要的是直接的字符串值。
  2. 字段名映射问题:你的UserDetails类里字段叫details,但目标JSON里对应的键是family(看你实际输出已经是family,应该是已经补了@JsonProperty,但这里还是提一下避免遗漏)。

解决步骤

不需要写复杂的自定义序列化器,用Jackson自带的@JsonValue注解就能解决核心问题:

1. 修改FamilyIndividual类

给individual字段加上@JsonValue注解,告诉Jackson直接序列化这个字段的字符串值,而不是整个对象:

@Data
@EqualsAndHashCode(callSuper = true)
public class FamilyIndividual extends AbstractFamilyDetails {
    @JsonValue
    private String individual;

    @Builder
    public FamilyIndividual(String individual) {
        super("FAMILY");
        this.individual = individual;
    }

    public FamilyIndividual() {
        super("FAMILY");
    }

    @Override
    public String toString() {
        return this.individual;
    }
}

2. 修正字段名映射(如果没做的话)

给UserDetails的details字段加上@JsonProperty("family"),确保序列化后的键名符合API要求:

public class UserDetails {
   private String firstName;
   @JsonProperty("family")
   private Map<String, AbstractFamilyDetails> details;
}

验证效果

修改后生成的JSON会完全匹配API要求的格式:

{
  "firstName" : "XYZ",
  "family" : {
     "commonDetails" : {
         "secondName" : "ABC"
     }, 
     "1" : "Mother name",
     "2" : "Father name",
     "3" : "Spouse name"
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 15:24:40