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

xesrikrc  于 2023-04-03  发布在  其他
关注(0)|答案(1)|浏览(108)

我有一个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反序列化忽略名称以下划线开头的任何属性,但如果发现任何其他未知属性,则会失败?

6ovsh4lw

6ovsh4lw1#

这并不像我想的那么简单,但一个解决方案是将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;
    }
}

相关问题