如何用Jackson将JSON数组反序列化为Kotlin数据类?
如何使用Jackson将JSON数组转换为指定Kotlin类?
给定如下JSON:
["answer", 42]
以及对应的Kotlin数据类:
data class JsonRow(val s: String, val n: Int)
如何使用Jackson将该数组转换为上述类?
最小可复现示例(Kotlin代码,Java场景下问题一致)
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import kotlin.test.Test import kotlin.test.assertEquals data class JsonRow(val s: String, val n: Int) object Example { @Test fun example() { // Given val jsonArray = """["answer", 42]""" val objectMapper = jacksonObjectMapper() // When val actual = objectMapper.readValue<JsonRow>(jsonArray) // Then val expected = JsonRow("answer", 42) assertEquals(expected, actual) } }
测试执行失败,报错信息如下:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of typecom.example.JsonRowfrom Array value (tokenJsonToken.START_ARRAY) at [Source: (String)"["answer", 42]"; line: 1, column: 1]
解决方案
方法1:用@JsonFormat指定数组映射规则
直接在数据类上添加注解,告诉Jackson该类需要从JSON数组反序列化,属性会按声明顺序匹配数组元素:
import com.fasterxml.jackson.annotation.JsonFormat import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import kotlin.test.Test import kotlin.test.assertEquals @JsonFormat(shape = JsonFormat.Shape.ARRAY) data class JsonRow(val s: String, val n: Int) object Example { @Test fun example() { val jsonArray = """["answer", 42]""" val objectMapper = jacksonObjectMapper() val actual = objectMapper.readValue<JsonRow>(jsonArray) val expected = JsonRow("answer", 42) assertEquals(expected, actual) } }
方法2:用@JsonProperty自定义元素映射顺序
如果数组元素顺序和类属性声明顺序不一致,可通过注解指定每个属性对应数组的索引位置:
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import kotlin.test.Test import kotlin.test.assertEquals data class JsonRow( @JsonProperty(index = 0) val s: String, @JsonProperty(index = 1) val n: Int ) object Example { @Test fun example() { val jsonArray = """["answer", 42]""" val objectMapper = jacksonObjectMapper() val actual = objectMapper.readValue<JsonRow>(jsonArray) val expected = JsonRow("answer", 42) assertEquals(expected, actual) } }
方法3:自定义反序列化器(处理复杂逻辑)
如果需要对数组元素做额外处理(比如类型转换、参数校验),可以自定义反序列化逻辑:
import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue import kotlin.test.Test import kotlin.test.assertEquals data class JsonRow(val s: String, val n: Int) class JsonRowDeserializer : JsonDeserializer<JsonRow>() { override fun deserialize(p: JsonParser, ctxt: DeserializationContext): JsonRow { val array = p.readValueAsArray<String>() return JsonRow(array[0], array[1].toInt()) } } object Example { @Test fun example() { val jsonArray = """["answer", 42]""" val module = SimpleModule().addDeserializer(JsonRow::class.java, JsonRowDeserializer()) val objectMapper = jacksonObjectMapper().registerModule(module) val actual = objectMapper.readValue<JsonRow>(jsonArray) val expected = JsonRow("answer", 42) assertEquals(expected, actual) } }
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

