Jackson 2.15.2 CsvMapper导出时setDateFormat不生效?
Jackson CsvMapper导出LocalDate自定义日期格式不生效问题
我使用Jackson 2.15.2的CsvMapper导出自定义日期格式时,输出结果始终是LocalDate#toString()的格式(如2023-12-04),而非指定的dd.MM.yyyy格式。测试代码执行后断言失败,错误信息如下:
org.opentest4j.AssertionFailedError: 2023-12-04 does not contain 04.12.2023 ==> Expected:true Actual:false
完整测试代码:
class CsvExportDateFormatTest { @Test void csvExportDateFormatTest() throws IOException { LocalDate now = LocalDate.now(); String pattern = "dd.MM.yyyy"; String formatted = DateTimeFormatter.ofPattern(pattern) .format(now); CsvMapper mapper = CsvMapper.builder() .addModule(new JavaTimeModule()) .configure(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS, false) .configure(CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING, true) .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) .build(); mapper.setDateFormat(new SimpleDateFormat(pattern)); List<MyClass> l = new ArrayList<>(); l.add(new MyClass(now)); CsvSchema schema = mapper.schemaFor(MyClass.class); StringWriter sw = new StringWriter(); mapper.writer(schema) .writeValue(sw, l); Assertions.assertTrue(sw.toString() .contains(formatted), sw + " does not contain " + formatted); } static class MyClass { private LocalDate now; public MyClass(LocalDate now) { this.now = now; } public LocalDate getNow() { return now; } public void setNow(LocalDate now) { this.now = now; } } }
问题原因与修复方法
你代码里有两个关键错误导致格式不生效:
setDateFormat不支持Java 8日期类型:SimpleDateFormat是为旧的java.util.Date等类设计的配置,LocalDate属于Java 8新日期API,这个全局配置对它完全无效。- JavaTimeModule默认序列化规则:添加
JavaTimeModule后,默认会用LocalDate.toString()的格式输出,没有指定自定义格式的话不会自动应用你想要的模式。
修复方案一:全局配置序列化格式
修改CsvMapper的构建逻辑,为JavaTimeModule添加自定义的LocalDate序列化器:
String pattern = "dd.MM.yyyy"; DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); // 自定义JavaTimeModule,添加LocalDate序列化器 JavaTimeModule module = new JavaTimeModule(); module.addSerializer(LocalDate.class, new LocalDateSerializer(formatter)); CsvMapper mapper = CsvMapper.builder() .addModule(module) .configure(CsvGenerator.Feature.ALWAYS_QUOTE_STRINGS, false) .configure(CsvGenerator.Feature.STRICT_CHECK_FOR_QUOTING, true) .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) .build(); // 移除mapper.setDateFormat(new SimpleDateFormat(pattern));这一行无效代码
修复方案二:字段级注解指定格式
直接在实体类的LocalDate字段上添加@JsonFormat注解,局部指定格式:
import com.fasterxml.jackson.annotation.JsonFormat; static class MyClass { @JsonFormat(pattern = "dd.MM.yyyy") private LocalDate now; // 构造器、getter、setter保持不变 }
这种方式无需修改Mapper配置,适合仅需为个别字段定制格式的场景。
内容的提问来源于stack exchange,提问作者Gunnar
相关产品推荐
相关产品推荐

