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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:25:01