Mike Emery
Mike Emery

Reputation: 837

How to make Kotlin Jackson CSV reader map column names to POJO?

Most Jackson plugins can map to different or out-of-order names with no problem, but I'm having trouble getting jackson-dataformat-csv to do it. It ignores any @JsonProperty and instead appears to populate based on POJO member order of appearance at compile time. If I read the CSV into a List<Map<String, String>> first, I can then convert it into the POJO with no issues. Am I missing a flag or what?

Trivial kotlin example (note that CSV order is intentionally different from POJO order):

class JacksonCSVTest {

    val sampleCsv = """
        A,c,BAD_HEADER BAD
        1,3,2
    """.trimIndent()

    class Foo {
        @JsonProperty("A")
        var a: Int = 0
        @JsonProperty("BAD_HEADER BAD")
        var b: Int = 0
        var c: Int = 0

        override fun toString(): String = "Foo(a=$a, b=$b, c=$c)"
    }

   @Test
    fun testDirectReader() {
        val csvMapper = CsvMapper()
        val schema = csvMapper.schemaFor(Foo::class.java).withHeader()
        val foos = csvMapper.readerFor(Foo::class.java).with(schema).readValues<Foo>(sampleCsv).readAll()
        val foo = csvMapper.convertValue(foos.single(), Foo::class.java)
        println(foo)
    }

    @Test
    fun testMapReader() {
        val csvMapper = CsvMapper()
        val schema = CsvSchema.emptySchema().withHeader()
        val map = csvMapper
            .readerFor(HashMap::class.java)
            .with(schema)
            .readValues<HashMap<String, String>>(sampleCsv)
            .readAll()
        val foo = csvMapper.convertValue(map.single(), Foo::class.java)
        println(foo)
    }
}

results in:

Foo(a=1, b=3, c=2)
 > testDirectReader (0.19s)
Foo(a=1, b=2, c=3)
 > testMapReader (0.01s)

The direct reader version has not placed column BAD_HEADER BAD with the correct variable. The map reader version placed it correctly.

What's going on here?

Upvotes: 1

Views: 1524

Answers (2)

wtsiamruk
wtsiamruk

Reputation: 339

To tell CsvMapper which column is which property you should specify a @JsonPropertyOrder annotation on top of a class

example for kotlin:

@JsonPropertyOrder({ "a", "b" })
data class CsvLine(val a: String, val b: String)

Upvotes: 2

Sunny Pelletier
Sunny Pelletier

Reputation: 379

I don't know about this jackson's bug, and I had a few problems with it too when parsing CSVs.

If you are still looking to do that, I created my own CSV library called Kotlin CSV Stream after facing too many problems with Jackson's CSV parser...

Upvotes: 0

Related Questions