假设我使用Open CSV,设置如下:
public class MyDto {
@CsvBindByName(column = "AFBP")
String placeholderA;
@CsvBindByNames({
@CsvBindByName(column = "ABCD"),
@CsvBindByName(column = "AFEL")
})
String placeholderB;
@CsvBindByNames({
@CsvBindByName(column = "ABCD"),
@CsvBindByName(column = "ALTM")
})
String placeholderC;
@Override
public String toString() {
return "placeholder A = " + placeholderA + ", placeholderB = " + placeholderB + ", placeholderC = " + placeholderC;
}
}
反序列化后
var csv = "AFBP,ABCDnthis is A,this is B and C";
我得到
placeholder A = this is A, placeholderB = null, placeholderC = this is B and C
而不是what I need:
placeholder A = this is A, placeholderB = this is B and C, placeholderC = this is B and C
是否有一种方法,使用这个库或类似的(提供对注释的支持),来反序列化CSV,使一列到多字段的映射成为可能?
不,这是不可能的,至少在OpenCSV版本5.7.1。然而,这可能会随着未来的版本而改变。
原因源于OpenCSV如何通过HeaderColumnNameMappingStrategy
注册bean/Pojos字段到列映射的方式。默认情况下用于CsvToBeanBuilder
:
这个构建器足够智能,可以猜测映射策略根据以下策略:
- 如果一个映射策略被显式设置,它总是被使用。
- 如果存在CsvBindByPosition或CsvCustomBindByPosition,则使用ColumnPositionMappingStrategy
- 否则使用
HeaderColumnNameMappingStrategy
。这包括使用CsvBindByName
或CsvCustomBindByName
的情况。的注释将被自动识别。
内部,类HeaderColumnNameMappingStrategy
将调用registerBinding(..)
。在这种情况下,Pojo的columnName(这里是:MyPojo
)被用作fieldMap
中映射信息的键。
遗憾的是,当前的实现没有检查,在第168行,如果一个键的映射已经存在(例如,ABCD
)。因此,它将用placeholderC
的新绑定覆盖第一个绑定字段placeholderB
。因此,解析将只识别它应该将值从csv输入映射到字段placeholderC
,如你所见。
侧节点:我测试了你的代码,可以确认你的问题给出的输出
我唯一想到的是:
- 写一个你自己的头(到)列名策略的实现。
- 从
HeaderNameBaseMappingStrategy
扩展开始。这样,您就可以正确地处理多次出现的现有字段到列映射。 - 显然,您需要使用
CsvToBeanBuilder#withMappingStrategy(..)
方法注册您的自定义或多字段策略。
因此,您可以打开更改请求来支持所需的行为。这样,现有的映射策略就可以得到改进,以应对您在这里提出的问题所带来的需求。
目前,似乎没有其他选项存在。