尽管有架构配置,但Jackson CsvMapper无法正确地反序列化为POJO

时间:2017-11-22 02:37:04

标签: java csv jackson-databind jackson-dataformat-csv

出于某种原因,尽管配置了FasterXML Jackson CSV映射器来创建基于POJO的架构,但它坚持认为没有提供合适的配置。我得到以下异常:

com.fasterxml.jackson.databind.JsonMappingException: No value type configured for ObjectReader
com.fasterxml.jackson.databind.ObjectReader._findRootDeserializer(ObjectReader.java:1371)
com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1265)
com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:897)
aol.model.core.services.admin.CSVParserService.parseCSVFileStreamAsClass(CSVParserService.java:42)
aol.rest.controller.AdminController.importCsvData(AdminController.java:30)
aol.rest.controller.AdminController$$FastClassBySpringCGLIB$$b9304c43.invoke(<generated>)
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
...

我的POJO很简单

@JsonPropertyOrder({"firstName", "lastName", "age"})
public class Person {
    String firstName;
    String lastName;
    Integer age;
    public Person() {} //no other use than to avoid no-suitable-construction found issue
    //getters and setters omitted for brevity
}

我的解析代码是

public MappingIterator<Person> parseCSVFileStreamAsClass(MultipartFile file) throws IOException {
        StringBuilder lines = new StringBuilder();
        String lineSeparator = System.getProperty("line.separator");
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
            for (String r = reader.readLine(); r != null; r = reader.readLine()) {
                lines.append(r).append(lineSeparator);
            }
        }

        CsvMapper mapper = new CsvMapper();
        CsvSchema schema = mapper
                .schemaFor(Person.class)
                .withHeader()
                .withLineSeparator(lineSeparator);
        MappingIterator<Person> out = mapper.reader(schema).readValue(lines.toString());
        return out;
    }

我以这种方式处理MultipartFile的原因不是直接读取流,而是消除了文件和映射器之间不匹配行分隔符的问题(我在Windows上工作[不要向下投票我:(])和映射器的默认行separator只有\n

数据文件是这个

  

名字,姓氏,年龄

     

“保”, “史密斯”, “22”

     

“简”, “克拉斯”, “98”

我尝试添加和删除引号(默认字符串分隔符)。我试过没有年龄数字的引号,然后把它们加入绝望之中。没有快乐!

我查看了documentation其他SO问题以及博文。没有运气。

2 个答案:

答案 0 :(得分:3)

好的,所以我的同事弄明白了。

MappingIterator<Person> out = mapper.reader(schema).readValue(lines.toString());

需要更改为

MappingIterator<Person> out = mapper.reader(Person.class).with(schema).readValue(lines.toString());

剩下的很好

答案 1 :(得分:1)

对以上答案的一个更正。它应该调用readValues()而不是readValue()方法

MappingIterator<Person> out = mapper.reader(Person.class).with(schema).readValues(lines.toString());