使用Spring Boot创建一个返回JSON有效负载的REST服务时,Java 8的LocalDateTime
被序列化。在将对象编组到字符串时,(大概)Jackson应用的格式字符串(即模式)在哪里,我在哪里可以找到应用该格式的Spring Boot中的默认配置(即设置格式化程序)?
(注意:我可以在有效负载中看到格式化的日期,而不是时间戳。)
答案 0 :(得分:0)
Jackson2ObjectMapperBuilder
在registerWellKnownModulesIfAvailable
方法中执行非常棘手的逻辑,用于注册多个模块。特别是对于java 8时间:
// Java 8 java.time package present?
if (ClassUtils.isPresent("java.time.LocalDate", this.moduleClassLoader)) {
try {
Class<? extends Module> javaTimeModule = (Class<? extends Module>)
ClassUtils.forName("com.fasterxml.jackson.datatype.jsr310.JavaTimeModule", this.moduleClassLoader);
objectMapper.registerModule(BeanUtils.instantiateClass(javaTimeModule));
}
catch (ClassNotFoundException ex) {
// jackson-datatype-jsr310 not available
}
}
因此,如果您的应用程序依赖jackson-datatype-jsr310
模块spring将默默注册它。因此,您将从此模块为java时间类型提供专用的序列化器/反序列化器。你对LocalDateTimeSerializer
感兴趣。正如您所看到的,序列化逻辑依赖于useTimestamp
,在您的情况下返回false,因此我们转移到else
分支。默认情况下,_formatter
为空,使用的_defaultFormatter()
为DateTimeFormatter.ISO_LOCAL_DATE_TIME
。如果要将日期序列化为字符串,或者通过从if
方法返回true
来使用useTimestamp
分支中的序列化逻辑,则可以通过提供自定义格式化程序轻松更新此行为。
@Override
public void serialize(LocalDateTime value, JsonGenerator g, SerializerProvider provider)
throws IOException
{
if (useTimestamp(provider)) {
g.writeStartArray();
g.writeNumber(value.getYear());
g.writeNumber(value.getMonthValue());
g.writeNumber(value.getDayOfMonth());
g.writeNumber(value.getHour());
g.writeNumber(value.getMinute());
if (value.getSecond() > 0 || value.getNano() > 0) {
g.writeNumber(value.getSecond());
if(value.getNano() > 0) {
if (provider.isEnabled(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS))
g.writeNumber(value.getNano());
else
g.writeNumber(value.get(ChronoField.MILLI_OF_SECOND));
}
}
g.writeEndArray();
} else {
DateTimeFormatter dtf = _formatter;
if (dtf == null) {
dtf = _defaultFormatter();
}
g.writeString(value.format(dtf));
}
}
// since 2.7: TODO in 2.8; change to use per-type defaulting
protected DateTimeFormatter _defaultFormatter() {
return DateTimeFormatter.ISO_LOCAL_DATE_TIME;
}
protected boolean useTimestamp(SerializerProvider provider) {
if (_useTimestamp != null) {
return _useTimestamp.booleanValue();
}
// assume that explicit formatter definition implies use of textual format
if (_formatter != null) {
return false;
}
return provider.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}