Skip to content

Instantly share code, notes, and snippets.

@efenderbosch
Last active September 23, 2020 17:18
Show Gist options
  • Save efenderbosch/e0906f02c66cf524c947da9b0db4d521 to your computer and use it in GitHub Desktop.
Save efenderbosch/e0906f02c66cf524c947da9b0db4d521 to your computer and use it in GitHub Desktop.
Jackson Validation
dependencies {
implementation("org.hibernate.validator:hibernate-validator:6.1.5.Final")
implementation("javax.el:javax.el-api:3.0.0")
implementation("org.glassfish:javax.el:3.0.0")
}
import kotlin.annotation.AnnotationTarget.CLASS
@Target(CLASS)
annotation class JsonValidated
import com.fasterxml.jackson.databind.BeanDescription
import com.fasterxml.jackson.databind.DeserializationConfig
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier
import javax.validation.Validation
object ValidatingBeanDeserializerModifier : BeanDeserializerModifier() {
private val validator = Validation.byDefaultProvider()
.configure()
.buildValidatorFactory()
.validator
override fun modifyDeserializer(
config: DeserializationConfig,
beanDesc: BeanDescription,
deserializer: JsonDeserializer<*>
) = if (beanDesc.classAnnotations.has(JsonValidated::class.java)) {
ValidatingDeserializer(deserializer, validator)
} else {
deserializer
}
}
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.deser.std.DelegatingDeserializer
import javax.validation.Validator
class ValidatingDeserializer(
delegate: JsonDeserializer<*>,
private val validator: Validator
) : DelegatingDeserializer(delegate) {
override fun newDelegatingInstance(newDelegatee: JsonDeserializer<*>): JsonDeserializer<*> {
return ValidatingDeserializer(newDelegatee, validator)
}
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Any? {
return super.deserialize(p, ctxt)?.let { validate(it) }
}
private fun validate(deserialized: Any): Any {
val constraintViolations = validator.validate(deserialized)
when {
constraintViolations.isEmpty() -> return deserialized
else -> {
val message = constraintViolations.joinToString { it.message.format(it.invalidValue) }
throw JsonMappingException(null, message)
}
}
}
}
import com.fasterxml.jackson.databind.module.SimpleModule
import javax.validation.Validation
class ValidatingModule : SimpleModule() {
init {
setDeserializerModifier(ValidatingBeanDeserializerModifier)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment