使用CsvMapper解析CSV至Java对象时所有字段为null的问题排查
问题原因分析
核心问题出在CsvSchema的配置逻辑与CSV实际结构不匹配,以及手动构建Schema时的映射错误:
- 你手动构建
CsvSchema后调用了.withHeader(),这个配置会让Jackson认为你定义的Schema列名是CSV的表头,而CSV本身的第一行表头会被当作普通数据行处理。但你的模型类字段是绑定到CSV原始表头的,导致解析时没有匹配的字段映射,最终所有字段为null。 - 移除
FAIL_ON_UNKNOWN_PROPERTIES后报错,是因为解析器尝试把CSV原始表头(如FON KODU)直接映射到模型属性名(如fonKodu),但手动构建的Schema没有建立两者的关联,加上.withHeader()的逻辑冲突,导致解析器无法识别@JsonProperty的映射关系。
解决方案
方案一:自动从模型类生成Schema(推荐)
不需要手动定义Schema,让Jackson通过模型类的@JsonProperty注解自动匹配CSV表头,代码修改如下:
@SuppressWarnings("unchecked") private <T> List<T> parseDataWithCsvMapper(String csvData, Class<?> modelClass) { try { CsvMapper csvMapper = CsvMapper.builder() .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .build(); // 从模型类自动生成Schema,识别@JsonProperty映射,同时指定CSV第一行是表头 CsvSchema schema = csvMapper.schemaFor(modelClass).withHeader(); Reader reader = new StringReader(csvData); return (List<T>) csvMapper .readerFor(modelClass) .with(schema) .readValues(reader) .readAll(); } catch (IOException e) { throw new RuntimeException("Failed to parse CSV data", e); } }
说明:schemaFor(modelClass)会自动读取模型类的@JsonProperty注解,生成与CSV表头匹配的Schema;.withHeader()明确告诉解析器CSV第一行是表头,用于匹配模型字段。
方案二:手动构建Schema(需修正映射逻辑)
如果必须手动定义Schema,要去掉.withHeader(),同时为每个列指定对应的模型属性名:
CsvSchema schema = CsvSchema.builder() // 绑定CSV列名到模型属性名 .addColumn("FON KODU", CsvSchema.ColumnType.STRING).withProperty("fonKodu") .addColumn("FON UNVANI", CsvSchema.ColumnType.STRING).withProperty("fonUnvani") // 其余字段按此格式补充 .build(); // 不要调用.withHeader(),让解析器使用CSV本身的表头匹配Schema列
说明:.withProperty("fonKodu")明确建立了CSV列FON KODU与模型属性fonKodu的映射,去掉.withHeader()后,解析器会用CSV原始表头匹配Schema定义的列名。
额外注意事项
由于CSV包含土耳其语特殊字符(如Ö、İ),需确保CSV数据编码正确:
如果CSV是ISO-8859-9编码,需调整Reader的编码设置:
Reader reader = new InputStreamReader( new ByteArrayInputStream(csvData.getBytes(StandardCharsets.ISO_8859_9)), StandardCharsets.ISO_8859_9 );
内容的提问来源于stack exchange,提问作者Requiet
相关产品推荐
相关产品推荐

