I'm trying to parse String CSV data into a Java object using CsvMapper. Here's the CSV schema and data format during debugging:
Parsing Method:
@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();
CsvSchema schema = CsvSchema.builder()
.addColumn("FON KODU")
.addColumn("FON UNVANI")
...
.build()
.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);
}
}
When I didn't manually add columns for headers, the CSV Schema during debugging::*
[CsvSchema: columns=[], header? true, skipFirst? false, comments? false, any-properties? N/A]
csvData during debugging:
FON KODU,FON UNVANI,FON ISIN KODU,FON OPERATÖR KODU,PARA BİRİMİ,İŞLEM BAŞLANGIÇ SAATİ,…
AAK,ATA PORTFÖY ÇOKLU VARLIK DEĞİŞKEN FON,TRMAF1WWWWW4,ATA,TL,09:00,17:30,…
AAL,ATA PORTFÖY PARA PİYASASI (TL) FONU,TRMAALWWWWW5,ATA,TL,09:00,13:30,…
Java Model Class:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class TefasDataModel {
@JsonProperty("FON KODU")
private String fonKodu;
@JsonProperty("FON UNVANI")
private String fonUnvani;
// Remaining fields match CSV headers.
}
Despite this, the output objects have all fields set to null. Example output:
[
{ "fonKodu": null, "fonUnvani": null, ... }
]
What I’ve Tried:
When I remove .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
method I'm getting this error:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "FON KODU" (class com.isuite.services.datajet.job.TefasDataModel), not marked as ignorable (24 known properties: "fonSatisValorAtlatmaSaati", "yarimGunIptalSaati", "fiyatMarjOrani", "fonSatisFiyatValor", "geriAlisAdetKati", "fonIsinKodu", "fonGeriAlisFiyatValor", "satisAdetKati", "iptalSonSaati", "minSatisAdet", "fonGeriAlisValor", "islemBaslangicSaati", "maksGeriAlisAdet", "fonSatisValor", "fonKodu", "islemBitisSaati", "fonGeriAlisValorAtlatmaSaati", "fonOperatorKodu", "fonUnvani", "maksSatisAdet", "minGeriAlisAdet", "yarimGunFonGeriAlisValorAtlSaati", "paraBirimi", "yarimGunFonSatisValorAtlSaati"])
at [Source: (StringReader); line: 2, column: 5] (through reference chain: com.isuite.services.datajet.job.TefasDataModel["FON KODU"])
What might be causing this issue? How can I resolve it to correctly map the CSV data to the model?
After researching, I found that CsvSchema should be written like this, specifying the model we are converting and also defining the line and column separators:
public static <T> List<T> parseCsvData(String csvData, Class<T> modelClass) {
try {
CsvMapper csvMapper = CsvMapper.builder()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.build();
CsvSchema schema = csvMapper.typedSchemaFor(modelClass)
.withHeader()
.withColumnSeparator(',')
.withColumnReordering(true);
List<String> headers = schema.getColumnNames();
System.out.println("CSV Headers: " + headers);
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);
}
}