Kotlin中使用mapper.readValue时缺失字段的校验方案
解决Kotlin数据类Jackson映射时的必填字段校验问题
在不修改数据类字段可空性的前提下,有几种实用的方式来校验JSON载荷是否包含所有必填属性:
1. 先解析为JsonNode手动校验
先把JSON字符串解析成Jackson的JsonNode,提前检查所有必填字段是否存在,避免直接映射时抛出异常:
val mapper = ObjectMapper().registerModule(KotlinModule()) val jsonPayload = """{"customerId": "C123", "purchaseDate": 1718000000000}""" // 第一步:解析为JsonNode val jsonNode = mapper.readTree(jsonPayload) // 第二步:定义必填字段列表并检查 val requiredFields = listOf("purchaseId", "customerId", "purchaseDate") val missingFields = requiredFields.filter { !jsonNode.has(it) } if (missingFields.isNotEmpty()) { throw IllegalArgumentException("缺失必填字段:${missingFields.joinToString(", ")}") } // 第三步:校验通过后再映射到数据类 val example = mapper.treeToValue(jsonNode, Example::class.java)
这种方式完全可控,能自定义错误提示,还能扩展校验字段的有效性(比如检查字段是否为合法字符串/数字)。
2. 捕获Jackson的缺失字段异常
利用Jackson默认会抛出MismatchedInputException的特性,通过捕获异常来处理缺失字段的情况:
val mapper = ObjectMapper().registerModule(KotlinModule()) val jsonPayload = """{"customerId": "C123"}""" try { val example = mapper.readValue(jsonPayload, Example::class.java) // 处理正常映射后的业务逻辑 } catch (e: MismatchedInputException) { // 从异常信息提取缺失字段,或给出通用提示 val errorMsg = when { e.message?.contains("purchaseId") == true -> "缺失必填字段:purchaseId" e.message?.contains("customerId") == true -> "缺失必填字段:customerId" e.message?.contains("purchaseDate") == true -> "缺失必填字段:purchaseDate" else -> "JSON格式错误,缺失必填字段" } throw IllegalArgumentException(errorMsg) }
如果想更通用提取缺失字段,可以解析异常的message内容,或者使用Jackson异常的e.path属性获取出错的属性路径。
3. 结合Bean Validation做增强校验
如果需要同时做格式、长度等多维度校验,可以引入Bean Validation框架(如Hibernate Validator)配合使用:
先给数据类字段添加校验注解:
import javax.validation.constraints.NotNull data class Example( @NotNull val purchaseId: String, @NotNull val customerId: String, @NotNull val purchaseDate: Long )
然后配置校验器,在映射完成后主动校验:
import javax.validation.Validation val validator = Validation.buildDefaultValidatorFactory().validator try { val example = mapper.readValue(jsonPayload, Example::class.java) val violations = validator.validate(example) if (violations.isNotEmpty()) { val errorMsg = violations.joinToString(", ") { "${it.propertyPath}:${it.message}" } throw IllegalArgumentException("校验失败:$errorMsg") } // 处理业务逻辑 } catch (e: MismatchedInputException) { throw IllegalArgumentException("缺失必填字段") }
这种方式适合需要复杂校验规则的场景,能同时覆盖字段存在性和格式有效性校验。
内容的提问来源于stack exchange,提问作者joe
相关产品推荐
相关产品推荐

