简体   繁体   English

使用 Jackson 使用 POJO 中未定义的额外列解析 CSV

[英]Parse CSV with extra columns which are not defined in POJO using Jackson

I am trying to parse a CSV and serialize it using the Jackson library.我正在尝试解析 CSV 并使用 Jackson 库对其进行序列化。 I have tried several methods but can't get to ignore the extra columns in the CSV which are not defined in the POJO.我尝试了几种方法,但无法忽略 CSV 中未在 POJO 中定义的额外列。 Requirements:要求:

  1. The columns in the incoming CSV can be in any order.传入的 CSV 中的列可以按任何顺序排列。
  2. There can be some columns which are defined in POJO but not there in CSV (missing columns).可以有一些在 POJO 中定义但在 CSV 中没有定义的列(缺少列)。
  3. There can be some columns in the CSV which are not defined in POJO (extra columns). CSV 中可能有一些列没有在 POJO 中定义(额外列)。

I have already tried @JsonIgnoreProperties(true) and also tried to use DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES but nothing seems to work properly.我已经尝试过@JsonIgnoreProperties(true)并且也尝试过使用DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES但似乎没有什么能正常工作。

POJO: POJO:

public class student{
   @JsonProperty("STUDENT_NAME")
   private String name;

   @JsonProperty("DOB")
   private String dateOfBirth;

   @JsonProperty("ID")
   private String id;
}

CSV: CSV:

STUDENT_NAME,ID,STANDARD,DOB
John,1,4,01/02/2000
Doe,2,5,02/01/1999

I believe the issue is that you need to specify a specific Schema.我认为问题在于您需要指定特定的架构。

For the Student class defined thusly:对于如此定义的学生 class:

@JsonIgnoreProperties(ignoreUnknown = true)
public static class Student
{
    @JsonProperty("STUDENT_NAME")
    private String name;
        
    @JsonProperty("DOB")
    private String dateOfBirth;
        
    @JsonProperty("ID")
    private String id;

    ...
}

This approach appears to work (tested using a String input, but obviously can change to read a file):这种方法似乎有效(使用 String 输入进行测试,但显然可以更改为读取文件):

public static List<Student> parse(String inp) throws IOException
{
    CsvSchema schema = CsvSchema.builder()
            .addColumn("STUDENT_NAME")
            .addColumn("ID")
            .addColumn("DOB")
            .setReorderColumns(true)
            .setUseHeader(true)
            .build();

            CsvMapper mapper = new CsvMapper();
            MappingIterator<Student> iter = mapper
                    .readerFor(Student.class)
                    .with(schema)
                    .readValues(inp);
                
            List<Student> students = new ArrayList<>();
            while (iter.hasNext()) {
                students.add(iter.next());
            }
                
            return students;
}

Tested via:通过测试:

final String example = "STUDENT_NAME,ID,STANDARD,DOB\n"
        + "John,1,4,01/02/2000\n"
        + "Doe,2,5,02/01/1999";


@org.junit.Test
public void testViaInp() throws IOException
{
    List<Student> students = ParseCsvWithJackson.parse(example);
    Assert.assertNotNull("null students", students);
    Assert.assertEquals("Wrong # of students", 2, students.size());
        
    Student first = students.get(0);
    Assert.assertEquals("Wrong name", "John", first.getName());
    Assert.assertEquals("Wrong id", "1", first.getId());
        
    System.out.println(first);
}

Update: I added a test to use a csv file, and it passed the same tests with the one caveat that I needed to set skip empty lines as a blank line at the end of the file was creating an entry with null values.更新:我添加了一个使用 csv 文件的测试,它通过了相同的测试,但有一个警告,我需要设置跳过空行,因为文件末尾的空行正在创建一个具有 null 值的条目。

    private static CsvSchema getSchema()
    {
        return CsvSchema.builder().addColumn("STUDENT_NAME").addColumn("ID")
                .addColumn("DOB").setReorderColumns(true).setUseHeader(true)
                .build();

    }

    private static CsvMapper getMapper()
    {
        CsvMapper mapper = new CsvMapper();
        
        mapper.enable(CsvParser.Feature.SKIP_EMPTY_LINES);
        
        return mapper;
    }



    public static List<Student> parse(Path csvfile) throws IOException
    {
        CsvSchema schema = getSchema();
        
        CsvMapper mapper = getMapper();
        MappingIterator<Student> iter = mapper.readerFor(Student.class)
                .with(schema).readValues(csvfile.toFile());

        List<Student> students = new ArrayList<>();
        while (iter.hasNext()) {
            students.add(iter.next());
        }

        return students;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM