如何通过Jackson自动填充POJO中的自定义formattedDate字段
问题与解决方案
问题描述
现有如下POJO:
@Data @Builder @AllArgsConstructor @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class CalendarData { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy HH:mm:ss") // 需按客户端要求格式化日期,与date字段值对应 private String formattedDate; private long date; private String errorCode; private String subErrorCode; }
下游服务仅传入epoch格式的date字段,需要在运行时自动将date转换为指定格式的字符串并填充到formattedDate字段中,希望通过Jackson原生方式或自定义setter实现,而非单独编写格式化函数。
解决方案
方法一:自定义Setter方法
直接覆盖date字段的setter方法,在设置date的同时完成formattedDate的格式化填充。Lombok的@Data会自动生成默认setter,手动编写setter后会覆盖默认实现:
@Data @Builder @AllArgsConstructor @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public class CalendarData { private String formattedDate; private long date; private String errorCode; private String subErrorCode; // 自定义setDate方法,同步设置formattedDate public void setDate(long date) { this.date = date; // 定义日期格式化器,可根据需求调整时区(如改为ZoneId.of("UTC")) DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss") .withZone(ZoneId.systemDefault()); // 将epoch时间转换为指定格式字符串 this.formattedDate = formatter.format(Instant.ofEpochMilli(date)); } }
当Jackson反序列化时,会调用该自定义setter,自动完成formattedDate的填充,无需额外处理。
方法二:Jackson原生自定义反序列化器
如果需要对反序列化流程做更灵活的控制,可以自定义Jackson反序列化器:
- 编写自定义反序列化器类:
public class CalendarDataDeserializer extends StdDeserializer<CalendarData> { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss") .withZone(ZoneId.systemDefault()); public CalendarDataDeserializer() { super(CalendarData.class); } @Override public CalendarData deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); CalendarData data = new CalendarData(); long epochDate = node.get("date").asLong(); data.setDate(epochDate); // 格式化填充formattedDate data.setFormattedDate(FORMATTER.format(Instant.ofEpochMilli(epochDate))); // 填充其他可选字段 if (node.has("errorCode")) { data.setErrorCode(node.get("errorCode").asText()); } if (node.has("subErrorCode")) { data.setSubErrorCode(node.get("subErrorCode").asText()); } return data; } }
- 在POJO类上添加注解指定反序列化器:
@Data @Builder @AllArgsConstructor @NoArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) @JsonDeserialize(using = CalendarDataDeserializer.class) public class CalendarData { private String formattedDate; private long date; private String errorCode; private String subErrorCode; }
这种方式适合需要对反序列化流程做更多自定义操作的场景,但相比自定义setter会更繁琐。
内容的提问来源于stack exchange,提问作者NoobEditor
相关产品推荐
相关产品推荐

