使用 Jackson CSV 忽略特定列解析 CSV 文件
Ignore Specific Columns Parsing a CSV File with Jackson CSV
我的问题是我需要将具有任意 columns/order 的 CSV 文件解析为已知域 POJO(比如 Person)。我可以确定我需要处理哪些列,而忽略其余列。
选项 CsvParser.Feature.IGNORE_TRAILING_UNMAPPABLE" 似乎正是我所需要的,但我需要处理的列不一定在 CSV 文件的开头分组,我不能强制用户 "re-order" 他们上传的 CSV 文件的列。此外,有时我没有得到 header 行,但 UI 强制用户识别列并将此信息传递过来。
例如,我有以下 CSV 文件:
First Name,Last Name,Nickname,DOB,Occupation,Postal Code
Freddy,Benson,Ruprecht,08/14/45,Con Artist,76701
Lawrence,Jamieson,Prince,03/14/33,Con Artist,5201
Janet,Colgate,Jackal,03/13/55,Con Artist,90401
我只需要 6 列中的 4 列(名字、姓氏、出生日期、邮政编码),因为我的个人 POJO 只包括这些字段:
public class Person {
private String firstName;
private String lastName;
private LocalDate dob;
private String postalCode;
}
我已经为 Person 定义了一个 CsvSchema 类型,并指定了我感兴趣的列的顺序(名字、姓氏、IGNORE、DOB、IGNORE2、邮政编码),因为我想跳过列(昵称、职业)。然而,"IGNORE" 列在反序列化器中的映射过程中被忽略,我最终得到 "DOB" 的 "Nickname" 值,导致 DOB 字段的值无效。
请参考这个link提供
你应该能解决这个问题https://github.com/FasterXML/jackson-dataformat-csv/issues/82
我的错误是如下定义模式,这显然将模式与域 POJO 强耦合:
CsvSchema schema = mapper
.typedSchemaFor(Person.class)
.withSkipFirstDataRow(hasHeader)
.sortedBy(columnOrder.toArray(new String[columnOrder.size()]));
通过如下定义 schema/columns 解决,这似乎将模式松散地耦合到域 POJO:
CsvSchema schema = CsvSchema.builder()
.addColumn("firstName")
.addColumn("lastName")
.addColumn("ignore1")
.addColumn("dob")
.addColumn("ignore2")
.addColumn("postalCode")
.build();
CsvMapper mapper = new CsvMapper();
MappingIterator<Person> personIter = mapper
.readerFor(Person.class)
.with(schema)
.readValues(csvFile);
忽略未知可以实现如下图(使用jackson 2.13测试):
- 注释 POJO
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.LocalDate;
@JsonIgnoreProperties(ignoreUnknown = true) //this is the trick to ignore all undeclared columns
public class Person {
@JsonProperty("First Name") //declare what's needed
private String firstName;
private String lastName;
private LocalDate dob;
private String postalCode;
}
- 配置 csvSchema
CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = csvMapper
.schemaFor(Person.class)
.withHeader()//header defines the order
.withColumnReordering(true)//this allows columns to be in any order as long as there is a header
;
- 最后,用它来读取csv文件
csvMapper.readerFor(Person.class).with(csvSchema).readValues(csvFile)
我的问题是我需要将具有任意 columns/order 的 CSV 文件解析为已知域 POJO(比如 Person)。我可以确定我需要处理哪些列,而忽略其余列。
选项 CsvParser.Feature.IGNORE_TRAILING_UNMAPPABLE" 似乎正是我所需要的,但我需要处理的列不一定在 CSV 文件的开头分组,我不能强制用户 "re-order" 他们上传的 CSV 文件的列。此外,有时我没有得到 header 行,但 UI 强制用户识别列并将此信息传递过来。
例如,我有以下 CSV 文件:
First Name,Last Name,Nickname,DOB,Occupation,Postal Code
Freddy,Benson,Ruprecht,08/14/45,Con Artist,76701
Lawrence,Jamieson,Prince,03/14/33,Con Artist,5201
Janet,Colgate,Jackal,03/13/55,Con Artist,90401
我只需要 6 列中的 4 列(名字、姓氏、出生日期、邮政编码),因为我的个人 POJO 只包括这些字段:
public class Person {
private String firstName;
private String lastName;
private LocalDate dob;
private String postalCode;
}
我已经为 Person 定义了一个 CsvSchema 类型,并指定了我感兴趣的列的顺序(名字、姓氏、IGNORE、DOB、IGNORE2、邮政编码),因为我想跳过列(昵称、职业)。然而,"IGNORE" 列在反序列化器中的映射过程中被忽略,我最终得到 "DOB" 的 "Nickname" 值,导致 DOB 字段的值无效。
请参考这个link提供
你应该能解决这个问题https://github.com/FasterXML/jackson-dataformat-csv/issues/82
我的错误是如下定义模式,这显然将模式与域 POJO 强耦合:
CsvSchema schema = mapper
.typedSchemaFor(Person.class)
.withSkipFirstDataRow(hasHeader)
.sortedBy(columnOrder.toArray(new String[columnOrder.size()]));
通过如下定义 schema/columns 解决,这似乎将模式松散地耦合到域 POJO:
CsvSchema schema = CsvSchema.builder()
.addColumn("firstName")
.addColumn("lastName")
.addColumn("ignore1")
.addColumn("dob")
.addColumn("ignore2")
.addColumn("postalCode")
.build();
CsvMapper mapper = new CsvMapper();
MappingIterator<Person> personIter = mapper
.readerFor(Person.class)
.with(schema)
.readValues(csvFile);
忽略未知可以实现如下图(使用jackson 2.13测试):
- 注释 POJO
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.LocalDate;
@JsonIgnoreProperties(ignoreUnknown = true) //this is the trick to ignore all undeclared columns
public class Person {
@JsonProperty("First Name") //declare what's needed
private String firstName;
private String lastName;
private LocalDate dob;
private String postalCode;
}
- 配置 csvSchema
CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = csvMapper
.schemaFor(Person.class)
.withHeader()//header defines the order
.withColumnReordering(true)//this allows columns to be in any order as long as there is a header
;
- 最后,用它来读取csv文件
csvMapper.readerFor(Person.class).with(csvSchema).readValues(csvFile)