如何用Jackson反序列化无字段名的逗号分隔字符串至Kotlin数据类
逗号分隔字符串转Kotlin数据类的Jackson反序列化问题
待反序列化的JSON数据(修正语法错误后)
{ "data": { "type": 18, "msg": "firstName,lastName,15", "timestamp": 1551770400000 } }
目标Kotlin数据类
原数据类需调整构造参数可见性,否则Jackson无法完成属性映射:
class DataDto( val type: String, val timestamp: Long, val msg: DataMsgDto? ) { class DataMsgDto( val firstName: String, val lastName: String, val age: Long ) }
当前代码及问题
val payload: DataBuffer // 服务端返回的内容 val jsonNode = objectMapper.readTree(payload.toString(StandardCharsets.UTF_8)) objectMapper.treeToValue(jsonNode, DataDto::class.java)
由于msg字段是无字段名的逗号分隔字符串,Jackson无法自动将其映射为DataMsgDto对象,导致反序列化失败。
解决方案:自定义Jackson反序列化器
1. 编写针对DataMsgDto的自定义反序列化器
class DataMsgDeserializer : JsonDeserializer<DataMsgDto>() { override fun deserialize(p: JsonParser, ctxt: DeserializationContext): DataMsgDto { val msgStr = p.text ?: throw JsonParseException(p, "msg字段不能为空") val parts = msgStr.split(",") if (parts.size != 3) { throw JsonParseException(p, "msg格式错误,需包含3个逗号分隔的值") } return DataMsgDto( firstName = parts[0], lastName = parts[1], age = parts[2].toLongOrNull() ?: throw JsonParseException(p, "age必须为有效数字") ) } }
2. 在DataDto的msg字段上指定反序列化器
修改DataDto定义,添加@JsonDeserialize注解绑定自定义反序列化器:
class DataDto( val type: String, val timestamp: Long, @JsonDeserialize(using = DataMsgDeserializer::class) val msg: DataMsgDto? ) { class DataMsgDto( val firstName: String, val lastName: String, val age: Long ) }
3. 调整反序列化代码(可选优化)
确保ObjectMapper已注册Kotlin模块(需引入jackson-module-kotlin依赖),直接反序列化即可:
// 先配置ObjectMapper val objectMapper = ObjectMapper().registerModule(KotlinModule()) // 反序列化逻辑 val payload: DataBuffer val dataDto = objectMapper.readValue(payload.asInputStream(), DataDto::class.java)
额外说明
- 数据类构造参数必须添加
val或var,否则Jackson无法访问属性完成赋值;也可将类改为data class,效果一致。 - 自定义反序列化器中加入了格式校验,避免非法格式的字符串导致转换异常。
内容的提问来源于stack exchange,提问作者AnnKont
相关产品推荐
相关产品推荐

