简体   繁体   中英

Kotlin + Spring Boot default value for Int field from JSON

I am writing simple CRUD with Kotlin + Spring Boot + Hibernate and came up with the issue:

I have a field in User class called age and type Int

import javax.persistence.*
import javax.validation.constraints.NotBlank
import javax.validation.constraints.Size

@Entity
@Table(name = "users")
data class User(
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val id: Long,

        @NotBlank
        @Column(unique = true)
        @Size(min = 1, max = 100)
        val username: String,

        @NotBlank
        @Size(max = 50)
        val firstName: String,

        @Size(max = 50)
        val lastName: String?,

        @Size(min = 1, max = 100)
        val age: Int
)

Then I have post request which creates a user

@PostMapping
fun post(@RequestBody user: User): User {
    log.debug("POST: {}", user)
    return userRepository.save(user)
}

The problem is that when I miss age field in JSON it doesn't respond with 400 error, but defaults to 0 instead.

How do I make this field required ?

I think that a bigger problem is that you are using the same class (your entity) for multiple purposes. This makes this class very unflexible since you can't adapt it to the needs of your REST endpoint and to the needs of Hibernate as well.

What I'd do instead is having a boundary between the two (something like Clean Architecture would suggest to do):

data class UserDTO(val id: Long?,
        var username: String?,
        var firstName: String?,
        var lastName: String?,
        var age: Int?) {

    fun toUser() = User(
        id = id ?: signalError(),
        username = username ?: signalError(),
        firstName = firstName ?: signalError(),
        lastName = lastName ?: signalError(),
        age = age ?: signalError())

    private fun signalError() : Nothing = throw IllegalArgumentException(
        "Missing parameter in UserDTO.")

}

I solved the issue thanks to this post , also thanks to @Adam Arold for showing best practices.

I created new UserDTO class:

import ai.leavingstone.flywayspringdemo.domain.User
import javax.validation.constraints.*

data class UserDTO(
        private val id: Long = -1,

        @field:NotBlank
        @field:Size(min = 1, max = 100)
        private val username: String,

        @field:NotBlank
        @field:Size(max = 50)
        private val firstName: String,

        @field:Size(max = 50)
        private val lastName: String?,

        @field:NotNull
        private val age: Int?
) {

    fun toUser(): User = User(
            id,
            username,
            firstName,
            lastName,
            age!!
    )

}

Before none of data validation annotations worked, after adding @field prefix it's working fine. @NotNull on Int is also working and default value for id field as well.

You should use @Valid @RequestBody user: User for the method parameter so spring is going to validate the given body. This should be done by default but just in case write it down and it´s better for new workers etc.

Also @ Size annotation does not support primitives or numeric vars. It just verifies a length of String , Array , Map , List ... So just annotate it with @Min and @Max . So the default Value of 0 would not be valid anymore.

Also for a nullable object to validate you can use Integer instead of Int so you can check just @NotNull if you want negatives or 0 be valid, too without getting default value 0.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM