如何使Kotlin-Jackson CSV阅读器将列名映射到POJO



大多数Jackson插件可以毫无问题地映射到不同或无序的名称,但我很难让jackson-dataformat-csv执行此操作。它忽略任何@JsonProperty,而是在编译时根据POJO成员的出现顺序进行填充。如果我先将CSV读取为List<Map<String, String>>,那么我就可以毫无问题地将其转换为POJO。我是不是错过了一面旗帜?

琐碎的kotlin示例(注意CSV订单有意与POJO订单不同(:

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)
}
}

结果在:

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

直接读卡器版本未将列BAD_HEADER BAD与正确的变量一起放置。地图阅读器版本正确放置了它。

这是怎么回事?

要告诉CsvMapper哪个列是哪个属性,您应该在类的顶部指定@JsonPropertyOrder注释

kotlin的示例:

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

我不知道这个jackson的bug,在解析CSV时也遇到了一些问题。

如果你仍然想这样做,在Jackson的CSV解析器遇到太多问题后,我创建了自己的CSV库Kotlin CSV Stream。。。

最新更新