我正在使用opencsv创建像这样的CsvToBean:

CsvToBean<AccountBean> csvToBean = new CsvToBeanBuilder<AccountBean>(new InputStreamReader(inputStream))
                .withFieldAsNull(CSVReaderNullFieldIndicator.NEITHER)
                .withType(AccountBean.class)
                .build();

这是我的AccountBean:
public class AccountBean extends BeanBase<Account>
{

    @CsvBindByName(column = "Id", required = true)
    public String salesforceId;

    @CsvBindByName(column = "OwnerId", required = true)
    public String ownerId;

    @CsvBindByName(column = "Name", required = true)
    public String name;

    // billing address
    @CsvBindByName(column = "BillingStreet")
    String billingStreet;
    @CsvBindByName(column = "BillingCity")
    String billingCity;
    @CsvBindByName(column = "BillingState")
    String billingState;
    @CsvBindByName(column = "BillingPostalCode")
    String billingPostcode;
    @CsvBindByName(column = "BillingCountry")
    String billingCountry;

}

问题在于地址字段-如果存在空白字段,则无论我将哪个CSVReaderNullFieldIndicator值传递给.withFieldAsNull(),它们始终为null。

我的csv文件用双引号引起来表示一个空字段,因此使用CSVReaderNullFieldIndicator.NEITHER(始终为默认值)应产生一个空字符串。

这会导致问题,因为我将null保存到数据存储中,然后在以后导致NullPointerExceptions。

我做错了什么?

最佳答案

我正在尝试使用您的方法,但行为却相同。由于该库是开源的,因此我一直在寻找原因。

  • CsvToBean类中,您具有负责的CSVReader访问要读取的数据。
  • CSVReader内,您有一个CSVParser,它负责将一个字符串作为一个字符串,并根据定界符,引号和转义字符将其解析为其元素。
  • CSVParser包含CSVReaderNullFieldIndicator(枚举)的成员,该成员用于告诉CSVParser考虑什么为空。

  • 当您在代码CsvToBean中调用build()时,将根据传递给CSVReader的信息实例化CSVParserCsvToBeanBuilder

    当您调用parse()时,CSVReader将遍历您的CSV文件,每行将调用CSVParser。根据您的分隔符,解析器将返回一个String值数组。此时,基于NullFieldIndicator的CSVParser将考虑将字符串保留为空或将其保留为null。最后,如果您具有NullFieldIndicator属性作为NEITHER,并且考虑的行是例如“one”;“”,则解析器返回的字符串数组将为[one,“”]或如果为CSVReaderNullFieldIndicator,则为[one,null]是BOTHEMPTY_QUOTES

    在此阶段之后,已解析的行将映射到AccountBean字段。为了确定该字段为空,使用StringUtils.isNotBlank()

    结论:不管您通过FieldAsNull()传递给什么,因为null将“”或false视为StringUtils.isNotBlank(),因此该字段将为null。

    您可以询问开发人员此行为是否符合预期。也许他有原因,或者只是一个错误。

    09-26 16:54