使用自定义分隔符列解析CSV不能正确映射到POJO

时间:2019-01-27 12:17:04

标签: java csv spring-boot

使用自定义列分隔符“;”解析CSV时并使用:

import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;

我收到以下错误:

com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class Author] from String value ('Email;FirstName;LastName'); no single-String constructor/factory method

这是我的解析代码:

public static <T> List<T> loadObjectList(Class<T> type, String fileName) {
     CsvSchema bootstrapSchema = CsvSchema.emptySchema();
     bootstrapSchema.withColumnSeparator(';').withoutQuoteChar();
     CsvMapper mapper = new CsvMapper();
     File file = new File(fileName);
     MappingIterator<T> readValues = 
         mapper.reader(type)
            .with(bootstrapSchema)
            .readValues(new InputStreamReader(new FileInputStream(file), "ISO-8859-1"));
     return readValues.readAll();
}

这是我想将CSV映射到的模型:

@JsonPropertyOrder({ "Email", "FirstName", "LastName" })
public class Author {

    String Email;
    String FirstName;
    String LastName;

    public String getEmail() {
        return Email;
    }

    public void setEmail(String Email) {
        this.Email = Email;
    }

    public String getFirstName() {
        return FirstName;
    }

    public void setFirstName(String firstName) {
        FirstName = firstName;
    }

    public String getLastName() {
        return LastName;
    }

    public void setLastName(String lastName) {
        LastName = lastName;
    }

    public Author(String email, String firstName, String lastName) {
        Email = email;
        FirstName = firstName;
        LastName = lastName;
    }

}

3 个答案:

答案 0 :(得分:1)

通常是这样, 解决问题的方法是:注意异常消息。

这是您包含的异常消息:

  

com.fasterxml.jackson.databind.JsonMappingException:无法从字符串值(“ Email; FirstName; LastName”)实例化[简单类型,类Author]类型的值。没有单字符串构造函数/工厂方法

这是您的问题的三步解决方案:

第1步:在异常消息中注意到这一点:没有单字符串构造函数/工厂方法

第2步:看看您包括的Author类。 请注意,它不包含接受构造函数或工厂方法的工厂 只是一个字符串作为参数。

第3步:向Author类添加一个接受单个String作为参数的构造函数。

这是一些代码(这不是最终代码,您将需要添加错误处理):

public Author(final String line)
{
  final String[] lineContentArray = line.split(";");

  // Note: consider using the standard java field naming convention.
  email = line[0];
  firstName = line[1];
  lastName = line[2];
}

答案 1 :(得分:0)

CsvSchema bootstrapSchema = CsvSchema.emptySchema();
bootstrapSchema.withColumnSeparator(';').withoutQuoteChar();

我不确定这部分-它不是构建器模式。

尝试

CsvSchema bootstrapSchema = CsvSchema.emptySchema().bootstrapSchema.withColumnSeparator(';').withoutQuoteChar();

相反。

答案 2 :(得分:0)

接受的答案的确可以根据对异常消息的建议来解决OP问题。 但是,使用CSVMapper的要点是不编写用于分隔符和字段分配的代码。这就是库应该做的。

当我遇到相同的问题时,我进行了一些挖掘并找到了以下内容。所有使用typedSchemaFor都是如此,其中type是目标类。 确实,必须同时对映射器和架构都使用type有点困扰。

ObjectReader objectReader() {
  CsvMapper mapper = new CsvMapper();
  CsvSchema schema = schema(mapper);
  return mapper.readerFor(type).with(schema);
}
    
CsvSchema schema(CsvMapper mapper) {
  return mapper.typedSchemaFor(type)
    .withColumnSeparator(';')
    .withoutHeader()
    .withoutQuoteChar();
}