Spring Data Rest与Kotlin中只读JSON字段的实体创建失败问题
问题解决:Spring Boot + Kotlin 实现非空只读字段自动赋值
错误原因
你遇到的空值错误,核心原因是:
- Kotlin 主构造函数的
name参数是非空类型且无默认值 @JsonProperty(access = READ_ONLY)会让Jackson反序列化时忽略该字段,导致无法为构造函数提供name的有效值,触发非空类型校验错误- 自定义反序列化器未生效,是因为
READ_ONLY标记让Jackson根本不会尝试处理该字段的反序列化逻辑
推荐解决方案(无需自定义反序列化器)
利用JPA生命周期注解+Jackson只读配置,同时给构造函数参数加默认值,既满足数据库非空约束,又实现API只读且自动赋值:
修改实体类代码
import com.fasterxml.jackson.annotation.JsonProperty import jakarta.persistence.* @Entity @Table(name = "cluster", schema = "public") class Cluster( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = 0, @Column(nullable = false, unique = true) @JsonProperty(access = JsonProperty.Access.READ_ONLY) var name: String = "", // 给构造函数加默认值,避免Jackson反序列化空值报错 ) { @PrePersist fun prePersist() { // 持久化到数据库前自动赋值,可替换为你的业务逻辑(比如生成唯一名称) if (name.isBlank()) { name = "Test Name" } } }
其他可选方案
方案二:Spring Data Rest 全局配置只读字段
通过配置类标记字段为只读,结合JPA自动赋值:
import org.springframework.context.annotation.Configuration import org.springframework.data.rest.core.config.RepositoryRestConfiguration import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer import org.springframework.web.servlet.config.annotation.CorsRegistry import models.Cluster @Configuration class RestConfig : RepositoryRestConfigurer { override fun configureRepositoryRestConfiguration(config: RepositoryRestConfiguration, cors: CorsRegistry) { // 标记Cluster的name字段为只读 config.getMetadataConfiguration() .addRepositoryMappingFor(Cluster::class.java) .addPropertyMapping("name").setReadOnly(true) } }
实体类保留@PrePersist和构造函数默认值即可,无需Jackson注解。
方案三:调整Jackson反序列化规则(不推荐)
如果必须使用自定义反序列化器,需关闭Jackson的缺失构造参数报错,并给构造函数参数加required=false:
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.annotation.JsonDeserialize import jakarta.persistence.* @Entity @Table(name = "cluster", schema = "public") class Cluster( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = 0, @Column(nullable = false, unique = true) @JsonProperty(access = JsonProperty.Access.READ_ONLY, required = false) @JsonDeserialize(using = CustomFieldDeserializer::class) var name: String, ) { // 次级构造函数配合默认值,避免Kotlin非空校验报错 constructor() : this(name = "") }
同时在application.yml中添加Jackson配置:
spring: jackson: deserialization: fail-on-missing-creator-properties: false
内容的提问来源于stack exchange,提问作者Grum
相关产品推荐
相关产品推荐

