You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Jackson CSV反序列化:忽略下划线开头属性,其余未知属性报错?

问题

我有一个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();
    }
}

标准CSV示例:

myString,myInt
A,1
B,2
C,3

需求是:反序列化时,若发现非下划线开头的未知属性则报错,避免因拼写错误导致应赋值的属性被设为null;同时允许CSV中包含以下划线开头的可选额外列(如_description、_notes),示例CSV如下:

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

要求不修改Java类注解(CSV反序列化是该对象的小众用法),实现上述配置。

解决方案

可以通过先过滤CSV表头、再配合Jackson反序列化特性来实现需求,具体步骤如下:

  1. 开启Jackson的FAIL_ON_UNKNOWN_PROPERTIES特性,确保非预期的未知属性会触发报错
  2. 提前读取CSV的表头,过滤掉所有以下划线开头的列
  3. 使用过滤后的表头构建CsvSchema,让Jackson只处理这些合法列,自动忽略下划线开头的列

完整实现代码

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CsvReader {

    public record MyType(String myString, Integer myInt) {}

    private List<MyType> readFile(Path file) throws IOException {
        // 配置Mapper:开启未知属性报错
        CsvMapper mapper = CsvMapper.csvBuilder()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
                .build();

        // 读取表头并过滤下划线开头的列
        List<String> filteredHeaders;
        try (BufferedReader reader = Files.newBufferedReader(file)) {
            String headerLine = reader.readLine();
            if (headerLine == null) {
                return Collections.emptyList();
            }
            filteredHeaders = Arrays.stream(headerLine.split(","))
                    .filter(columnName -> !columnName.startsWith("_"))
                    .toList();
        }

        // 用过滤后的表头构建Schema
        CsvSchema.Builder schemaBuilder = CsvSchema.builder();
        filteredHeaders.forEach(schemaBuilder::addColumn);
        CsvSchema schema = schemaBuilder.build();

        // 创建ObjectReader并读取数据
        ObjectReader objectReader = mapper.readerFor(MyType.class).with(schema);
        try (MappingIterator<MyType> iterator = objectReader.readValues(file.toFile())) {
            return iterator.readAll();
        }
    }
}

效果说明

  • 当下划线开头的列存在时:会被过滤掉,Jackson不会尝试反序列化这些列,不影响正常属性的赋值
  • 当出现非下划线开头的未知列(比如拼写错误的myStrng):Jackson会抛出UnrecognizedPropertyException,及时发现拼写错误问题
  • 不需要修改MyType实体类的任何注解,完全通过代码配置实现需求

内容的提问来源于stack exchange,提问作者M. Justin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 08:55:07