csv 如何将值从一列Map到多个字段?

f0brbegy  于 2022-12-06  发布在  其他
关注(0)|答案(1)|浏览(139)

假设我使用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,ABCD\nthis is A,this is B and C";

我得到了

placeholder A = this is A, placeholderB = null, placeholderC = this is B and C

而不是我所需要的

placeholder A = this is A, placeholderB = this is B and C, placeholderC = this is B and C

问题

有没有一种方法,使用这个库或类似的库(提供对注解的支持),来反序列化CSV,使一列到多个字段的Map成为可能?

xdnvmnnf

xdnvmnnf1#

,这是 * 不 * 可能的,至少在OpenCSV版本5.7.1中是这样。* 但是,这可能会在未来的发行版中更改。*

原因在于OpenCSV如何通过HeaderColumnNameMappingStrategy注册一个Beans/Pojos字段到列的Map。
此生成器足够智能,可以根据以下策略猜测Map策略
1.如果显式设置了Map策略,则始终使用该策略。
1.如果存在CsvBindByPosition或CsvCustomBindByPosition,则会使用数据行位置Map策略。
1.否则,使用HeaderColumnNameMappingStrategy。这包括使用CsvBindByNameCsvCustomBindByName的情况。注解将被自动识别。
在内部,类HeaderColumnNameMappingStrategy将调用registerBinding(..)MyPojo)用作fieldMap中的Map信息的关键字。
遗憾的是,在第168行,当前的实现没有检查是否已经存在键的Map(例如,ABCD)。因此,它将用placeholderC的新绑定覆盖第一个绑定字段placeholderB。结果,解析将只识别它应该将 csv 输入的值Map到字段**placeholderC**,正如您所观察到的。

  • 边节点:我测试了你的代码,可以确认输出如你的问题。*

我脑子里冒出的唯一念头是:

  • 编写您自己的标头(到)列名策略的实现。
  • 首先从HeaderNameBaseMappingStrategy开始扩展,这样就可以正确地处理现有的字段到列的Map。
  • 显然,您需要使用CsvToBeanBuilder#withMappingStrategy(..)方法注册自定义或多字段策略。

因此,您可以通过open a change request来支持所需的行为,这样,现有的Map策略就可以得到改进,以科普您在这里提出的问题所带来的需求。
目前,似乎没有其他选择。

相关问题