API二次调用报JSON反序列化错误:zipCode属性Setter冲突
问题分析
错误核心是Jackson反序列化MetaAddress中的Address对象时,发现zipCode属性存在两个冲突的setter方法:setZipCode(String)和setZipCode(String[])。即便给其中一个添加@JsonIgnore也无效,原因是Lombok的@Data注解会自动生成getter/setter,你手动编写的setter与自动生成的(或自身定义的另一个)形成重复定义;且单独使用Address类时,Jackson的处理逻辑与嵌套在MetaAddress中不同,导致冲突仅在嵌套场景暴露。
解决方案
方案1:合并setter逻辑,兼容两种输入格式
只保留一个setter方法,通过判断输入类型同时处理字符串和数组格式的zipCode,彻底避免方法冲突:
@Data @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public final class Address implements Serializable { private String id; private String zipCode; private String city; @JsonSetter public void setZipCode(Object zipCode) { if (zipCode instanceof String[]) { this.zipCode = ((String[]) zipCode)[0]; } else if (zipCode instanceof String) { this.zipCode = (String) zipCode; } // 可按需补充null或其他类型的处理逻辑 } }
方案2:禁用Lombok自动生成zipCode的setter,手动控制方法签名
通过@Setter(AccessLevel.NONE)阻止Lombok生成zipCode的setter,同时给数组版本的setter重命名,避免方法签名冲突:
@Data @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) // 禁止Lombok自动生成zipCode的setter @Setter(AccessLevel.NONE) public final class Address implements Serializable { private String id; private String zipCode; private String city; // 字符串版本setter标记为Jackson忽略,仅用于业务代码调用 @JsonIgnore public void setZipCode(String zipCode) { this.zipCode = zipCode; } // 数组版本setter指定对应json字段,方法名避免重复 @JsonSetter("zipCode") public void setZipCodeFromStringArray(String[] zipCode) { this.zipCode = zipCode[0]; } }
方案3:自定义Jackson反序列化器
通过自定义反序列化器完全控制zipCode的解析逻辑,无需编写多个setter:
- 编写反序列化器类:
public class ZipCodeDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node.isArray()) { return node.get(0).asText(); } else if (node.isTextual()) { return node.asText(); } return null; } }
- 在Address类的
zipCode字段上应用注解:
@Data @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public final class Address implements Serializable { private String id; @JsonDeserialize(using = ZipCodeDeserializer.class) private String zipCode; private String city; }
场景差异说明
单独使用Address类时,Jackson可能在首次序列化/反序列化时缓存了简化的类处理规则;而嵌套在MetaAddress中时,类的初始化或缓存逻辑触发了完整的方法校验,导致冲突被检测到。
内容的提问来源于stack exchange,提问作者Taha LAGHZALI
相关产品推荐
相关产品推荐

