Search code examples
jsonkotlinjacksonjava-record

Deserialize a JSON array to a data class or record


Given this JSON,

["answer", 42]

and an accompanying class,

data class JsonRow(val s: String, val n: Int)

how can I use jackson to convert the array to the class?


Minimal reproducible example (this is in Kotlin but as far as I can tell the same problem exists for 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)
    }
}

The test fails with:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.example.JsonRow` from Array value (token `JsonToken.START_ARRAY`) at [Source: (String)"["answer", 42]"; line: 1, column: 1]


Solution

  • The easiest thing to do is use the JsonFormat annotation to specify the data class's shape as an Array.

    For example, after adding this, everything works as expected

    import com.fasterxml.jackson.annotation.JsonFormat
    
    @JsonFormat(shape = JsonFormat.Shape.ARRAY)
    data class JsonRow(val s: String, val n: Int)