What is the spring batch way of formatting CSV fields individually? #4748
-
Before using Spring Batch I've been using @Data
public class DataModel{
@CsvCustomBindByPosition(position = 0, converter = BigDecimalCurrencyConverter.class)
@CsvBindByName(column = "Revenue (in $)")
private BigDecimal revenue;
} with public static class BigDecimalCurrencyConverter
extends AbstractBeanField<BigDecimal, BigDecimal> {
@Override
protected BigDecimal convert(String value)
throws CsvDataTypeMismatchException, CsvConstraintViolationException {
if (value == null || value.isEmpty()) {
return null;
}
var symbols = new DecimalFormatSymbols(Locale.getDefault());
symbols.setDecimalSeparator(',');
var decimalFormat = new DecimalFormat("#,##0.00", symbols);
decimalFormat.setParseBigDecimal(true);
try {
return (BigDecimal) decimalFormat.parse(value);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
@Override
protected String convertToWrite(Object value) {
if (value == null) {
return "";
}
var number = (BigDecimal) value;
var symbols = new DecimalFormatSymbols(Locale.getDefault());
symbols.setDecimalSeparator(',');
var decimalFormat = new DecimalFormat("#,##0.00", symbols);
return decimalFormat.format(number);
}
} With a little Reflection the fields were (de)serialized accordingly. Now I'm not sure how exactly to put this code to make the most out of it. I liked having it close to the model. I'm still using private static <T> String[] getCsvHeaderNames(Class<T> modelClass) {
return Arrays.stream(modelClass.getDeclaredFields())
.map(
field ->
field.getAnnotation(CsvBindByName.class) != null
? field.getAnnotation(CsvBindByName.class).column()
: field.getName())
.toArray(String[]::new);
} to get the headers for my |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The In your case, you can use a If you share a GitHub repo or a zip with a minimal code example / input file, I can try to help you implement the mapping logic with spring batch. |
Beta Was this translation helpful? Give feedback.
The
FieldSetMapper
is the main extension point for converting a typed fieldset to a domain object. There an are few implementations provided by spring batch, but you might need a custom one if nothing from the provided ones really help.In your case, you can use a
BeanWrapperFieldSetMapper
if the target type is a java class orRecordFieldSetMapper
for java records. Both provide a configurable conversion service in which you can register custom converter like the one you shared (you just need to adapt it to the expected conversion type).If you share a GitHub repo or a zip with a minimal code example / input file, I can try to help you implement the mapping logic with spring batch.