当Jackson反序列化时,我可以忽略源数据中匹配命名模式的属性吗?



我有一个Java对象,除其他外,它正在使用jackson-dataformat-csv从CSV格式反序列化。

public record MyType(String myString, Integer myInt) {}
private List<MyType> readFile(Path file) throws IOException {
CsvMapper mapper = CsvMapper.csvBuilder().build();
CsvSchema schema = CsvSchema.emptySchema().withHeader();
ObjectReader objectReader = mapper.readerFor(MyType.class).with(schema);
try (MappingIterator<MyType> iterator = objectReader.readValues(file.toFile())) {
return iterator.readAll();
}
}
myString,myInt
A,1
B,2
C,3

一般来说,如果发现未知属性,我希望反序列化失败,因为我不希望通过将应该有值的属性设置为null而使错别字弄乱数据。但是,我还希望能够选择性地包括帮助描述数据的额外列。确切的额外列可能因csv而异,并且无法提前知道。为了将这些列与其他列区分开来,我可以使用CSV列命名约定来指示我希望忽略的列(例如,用下划线作为前缀)。

myString,myInt,_description,_notes
A,1,Apple,
B,2,Ball,Only used in legacy data
C,3,Cat,Not used yet

话虽如此,我还没有想出一个干净的方法来告诉Jackson忽略基于前缀的列。

理想情况下,我不希望将注释添加到Java类本身,因为CSV反序列化是对象的一个非常小的用途(尽管这不是一个硬要求)。

是否有一种方法可以告诉Jackson反序列化忽略任何名称以下划线开头的属性,但如果发现任何其他未知属性则失败?

这并不像我想的那么简单,但是一种解决方案是将CSV转换为非结构化类型(ObjectNodeMap),用下划线键剥离值,然后将其转换为所需的类型。如果有任何剩余的不支持的属性,将按需要抛出UnrecognizedPropertyException

private List<MyType> readFile(Path file) throws IOException {
CsvMapper mapper = CsvMapper.csvBuilder().build();
CsvSchema schema = CsvSchema.emptySchema().withHeader();
ObjectReader objectReader = mapper.readerFor(ObjectNode.class).with(schema);
try (MappingIterator<ObjectNode> iterator = objectReader.readValues(file.toFile())) {
List<MyType> result = new ArrayList<>();
while (iterator.hasNextValue()) {
ObjectNode node = iterator.nextValue();
List<String> underscoreFields = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
node.fieldNames(), Spliterator.ORDERED), false)
.filter(f -> f.startsWith("_"))
.toList();
node.remove(underscoreFields);
result.add(mapper.treeToValue(node, MyType.class));
}
return result;
}
}