Jackson反序列化含可选List的Record遇SetterlessProperty问题求解
解决方案
针对Jackson反序列化Java Record时出现的Should never call set() on setterless property错误,以及可选List字段的处理需求,结合你的技术栈(jackson-databind 2.13.5、Spring Boot 2.7.11),以下是简洁规范的解决方法:
核心问题分析
Java Record是不可变类型,Jackson默认通过构造器完成反序列化,而非调用setter方法。之前的错误源于在Record属性上使用@JsonSetter,Jackson试图调用不存在的setter;自定义StringClone类属于冗余操作,直接使用List<String>即可满足需求。
方案一:用@JsonProperty统一字段映射(推荐)
直接在Record的构造器参数上添加@JsonProperty,同时控制反序列化(JSON→Record)和序列化(Record→JSON)的字段名,无需单独使用@JsonGetter/@JsonSetter,代码最简洁:
import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; // 同时作为反序列化目标和响应模型 public record MediaRecord( // 适配前后端不同字段名:JSON的user_id → Record的userId;序列化时userId输出为user_id @JsonProperty("user_id") String userId, // 处理可选字段:JSON的media_links_txt → Record的mediaLinks,缺失则为null @JsonProperty("media_links_txt") List<String> mediaLinks ) {}
方案二:针对特殊场景的@JsonGetter/@JsonSetter适配
如果需要对部分属性单独指定序列化输出的字段名(和反序列化输入字段名不同),可以在构造器参数用@JsonProperty处理输入,在getter方法上用@JsonGetter处理输出:
import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; public record MediaRecord( // 反序列化时映射JSON的user_id到userId @JsonProperty("user_id") String userId, // 反序列化时映射JSON的media_links_txt到mediaLinks,缺失则为null @JsonProperty("media_links_txt") List<String> mediaLinks ) { // 序列化时将userId输出为external_user_id(和输入字段名不同) @JsonGetter("external_user_id") public String getUserIdForResponse() { return this.userId; } }
配套Jackson配置(可选)
在Spring Boot中,添加以下配置确保可选字段和空值的正确处理:
方式1:application.yml配置
spring: jackson: deserialization: # 可选:将空数组转为null(如果业务需要) accept-empty-array-as-null-object: true # 可选:忽略JSON中未知字段,避免反序列化报错 fail-on-unknown-properties: false serialization: # 可选:序列化时忽略null字段(如果响应不需要返回null) write-null-map-values: false
方式2:Java配置类
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { return new ObjectMapper() .enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .disable(SerializationFeature.WRITE_NULL_MAP_VALUES); } }
关键注意事项
- Jackson 2.12+对Java Record的支持已经成熟,默认通过构造器注入属性,无需手动编写setter
- 可选字段直接定义为
List<String>,当JSON中缺失该字段时,Jackson会自动传入null到构造器(默认配置下) - 优先使用
@JsonProperty统一处理字段映射,比拆分@JsonGetter/@JsonSetter更简洁易维护
内容的提问来源于stack exchange,提问作者MarcelTon
相关产品推荐
相关产品推荐

