Tako
Tako

Reputation: 672

Set localized column title in CSV file using Jackson

I try to create a CSV file using jackson-dataformat-csv as described in this tutorial (Jackson Annotation method).

Here is the definition of my Csv lines :

@JsonPropertyOrder(value = {"foo", "bar"})
public class MyDataCsv implements Serializable {
    private String foo;

    private String bar;

    // getter & setter
    //...
}

And this is how I build my CSV using Jackson :

private void generateCsv(OutputStream o, List<MyDataCsv> data) {
    CsvMapper mapper = new CsvMapper();
    CsvSchema schema = mapper.schemaFor(MyDataCsv.class).withHeader();

    ObjectWriter objectWriter = mapper.writer(schema);
    objectWriter.writeValue(o, data);
}

In my output CSV I get this :

| foo  | bar  |
+------+------+
| foo1 | bar1 |
| foo2 | bar2 |
| foo3 | bar3 |

Is there a way to have column title not based on the property name ? I mean, how can I get for example this CSV with the label localized :

| ProperLabel_EN | ProperLabel2_EN |
+----------------+-----------------+
| foo1           | bar1            |
| foo2           | bar2            |
| foo3           | bar3            |

Or in french

| ProperLabel_FR | ProperLabel2_FR |
+----------------+-----------------+
| foo1           | bar1            |
| foo2           | bar2            |
| foo3           | bar3            |

Cheers

Upvotes: 0

Views: 8814

Answers (2)

user3088282
user3088282

Reputation: 106

It is a late answer sorry for that. The way I found for this problem is a little bit tricky.

Basically, csvMapper expects headers and property names exactly the same, otherwise It can not detect and map property values with related headers.

Thats why I manually added headers with the translated form of them for the CsvSchema.

Then to manipulate the property names I created a custom PropertyNamingStrategy.

Below you can find the code samples :

private CsvSchema prepareCsvSchema(List<CsvHeader> headers, ExportOptions options) {
    CsvSchema.Builder builder = CsvSchema.builder();

    for (CsvHeader header : headers) {
        String localizedHeader =  messageSource.getMessage(header.getPropertyKey(), null, options.getLocale());
        builder.addColumn(localizedHeader);
    }

    builder.setUseHeader(true)
            .setColumnSeparator(options.getColumnSeparator())
            .setArrayElementSeparator(options.getArraySeparator());

    return builder.build();

}



public class LocalizedPropertyNamingStrategy extends PropertyNamingStrategy {

private MessageSource messageSource;
private Locale locale;

LocalizedPropertyNamingStrategy(MessageSource messageSource, Locale locale) {
    this.messageSource = messageSource;
    this.locale = locale;
}

@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) {
    return localize(defaultName);
}

@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
    return localize(defaultName);
}

@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
    return localize(defaultName);
}

private String localize(String defaultName) {
    final String propertyKey = CsvHeader.getPropertyKeyByFieldName(defaultName);
    if (StringUtils.isNotEmpty(propertyKey)) {
        return messageSource.getMessage(propertyKey, null, locale);
    }
    return defaultName;
}

}

And then, while defining the mapper :

csvMapper = new CsvMapper();
csvMapper.setPropertyNamingStrategy(new LocalizedPropertyNamingStrategy(messageSource, locale));

Upvotes: 5

Ramachandra Reddy
Ramachandra Reddy

Reputation: 301

Have you tried using

@JsonProperty("ProperLabel")
private String foo;

Upvotes: 2

Related Questions