Make Joda DateTime serialization format configurable
We allow the serialization format of dates to be configured using spring.jackson.date-format. However, this property only applies to java.util.Date instances and has no effect on a Joda DateTime. This commit updates our auto-configuration for Jackson to allow the format string that is used to serialize a Joda DateTime to be configured. A new property, spring.jackson.joda-date-time-format has been introduced. When configured, it is used to configure the serialization format for a Joda DateTime. When it is not configured, we fall back to using spring.jackson.date-format. If this fails, either because the format string is incompatible (unlikely) or because the user's configured the fully-qualified name of a DateFormat class, a warning is logged encouraging the use of spring.jackson.joda-date-time-format. Fixes gh-2225
This commit is contained in:
parent
f11bcb9495
commit
201fb5e534
|
@ -25,6 +25,10 @@ import java.util.Map.Entry;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
|
@ -47,6 +51,9 @@ import com.fasterxml.jackson.databind.Module;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer;
|
||||
import com.fasterxml.jackson.datatype.joda.ser.JacksonJodaFormat;
|
||||
|
||||
/**
|
||||
* Auto configuration for Jackson. The following auto-configuration will get applied:
|
||||
|
@ -97,6 +104,50 @@ public class JacksonAutoConfiguration {
|
|||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Jackson2ObjectMapperBuilder.class, DateTime.class,
|
||||
DateTimeSerializer.class })
|
||||
static class JodaDateTimeJacksonConfiguration {
|
||||
|
||||
private final Log log = LogFactory.getLog(JodaDateTimeJacksonConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
private JacksonProperties jacksonProperties;
|
||||
|
||||
@Bean
|
||||
public Module jodaDateTimeSerializationModule() {
|
||||
SimpleModule module = new SimpleModule();
|
||||
|
||||
JacksonJodaFormat jacksonJodaFormat = null;
|
||||
|
||||
if (this.jacksonProperties.getJodaDateTimeFormat() != null) {
|
||||
jacksonJodaFormat = new JacksonJodaFormat(DateTimeFormat.forPattern(
|
||||
this.jacksonProperties.getJodaDateTimeFormat()).withZoneUTC());
|
||||
}
|
||||
else if (this.jacksonProperties.getDateFormat() != null) {
|
||||
try {
|
||||
jacksonJodaFormat = new JacksonJodaFormat(DateTimeFormat.forPattern(
|
||||
this.jacksonProperties.getDateFormat()).withZoneUTC());
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
if (this.log.isWarnEnabled()) {
|
||||
this.log.warn("spring.jackson.date-format could not be used to "
|
||||
+ "configure formatting of Joda's DateTime. You may want "
|
||||
+ "to configure spring.jackson.joda-date-time-format as "
|
||||
+ "well.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jacksonJodaFormat != null) {
|
||||
module.addSerializer(DateTime.class, new DateTimeSerializer(
|
||||
jacksonJodaFormat));
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass({ ObjectMapper.class, Jackson2ObjectMapperBuilder.class })
|
||||
@EnableConfigurationProperties({ HttpMapperProperties.class, JacksonProperties.class })
|
||||
|
|
|
@ -43,6 +43,13 @@ public class JacksonProperties {
|
|||
*/
|
||||
private String dateFormat;
|
||||
|
||||
/**
|
||||
* Joda date time format string (yyyy-MM-dd HH:mm:ss). If not configured,
|
||||
* {@code date-format} will be used as a fallback if it is configured with a format
|
||||
* string.
|
||||
*/
|
||||
private String jodaDateTimeFormat;
|
||||
|
||||
/**
|
||||
* One of the constants on Jackson's PropertyNamingStrategy
|
||||
* (CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES). Can also be a fully-qualified class
|
||||
|
@ -83,6 +90,14 @@ public class JacksonProperties {
|
|||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
public String getJodaDateTimeFormat() {
|
||||
return this.jodaDateTimeFormat;
|
||||
}
|
||||
|
||||
public void setJodaDateTimeFormat(String jodaDataTimeFormat) {
|
||||
this.jodaDateTimeFormat = jodaDataTimeFormat;
|
||||
}
|
||||
|
||||
public String getPropertyNamingStrategy() {
|
||||
return this.propertyNamingStrategy;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
@ -134,6 +135,23 @@ public class JacksonAutoConfigurationTests {
|
|||
"spring.jackson.date-format:yyyyMMddHHmmss");
|
||||
this.context.refresh();
|
||||
ObjectMapper mapper = this.context.getBean(ObjectMapper.class);
|
||||
DateTime dateTime = new DateTime(1988, 6, 25, 20, 30, DateTimeZone.UTC);
|
||||
assertEquals("\"19880625203000\"", mapper.writeValueAsString(dateTime));
|
||||
dateTime = new DateTime(1988, 6, 25, 20, 30);
|
||||
Date date = dateTime.toDate();
|
||||
assertEquals("\"19880625203000\"", mapper.writeValueAsString(date));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customJodaDateTimeFormat() throws Exception {
|
||||
this.context.register(JacksonAutoConfiguration.class);
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"spring.jackson.date-format:yyyyMMddHHmmss",
|
||||
"spring.jackson.joda-date-time-format:yyyy-MM-dd HH:mm:ss");
|
||||
this.context.refresh();
|
||||
ObjectMapper mapper = this.context.getBean(ObjectMapper.class);
|
||||
DateTime dateTime = new DateTime(1988, 6, 25, 20, 30, DateTimeZone.UTC);
|
||||
assertEquals("\"1988-06-25 20:30:00\"", mapper.writeValueAsString(dateTime));
|
||||
Date date = new DateTime(1988, 6, 25, 20, 30).toDate();
|
||||
assertEquals("\"19880625203000\"", mapper.writeValueAsString(date));
|
||||
}
|
||||
|
@ -147,6 +165,8 @@ public class JacksonAutoConfigurationTests {
|
|||
"spring.jackson.date-format:org.springframework.boot.autoconfigure.jackson.JacksonAutoConfigurationTests.MyDateFormat");
|
||||
this.context.refresh();
|
||||
ObjectMapper mapper = this.context.getBean(ObjectMapper.class);
|
||||
DateTime dateTime = new DateTime(1988, 6, 25, 20, 30, DateTimeZone.UTC);
|
||||
assertEquals("\"1988-06-25T20:30:00.000Z\"", mapper.writeValueAsString(dateTime));
|
||||
Date date = new DateTime(1988, 6, 25, 20, 30).toDate();
|
||||
assertEquals("\"1988-06-25 20:30:00\"", mapper.writeValueAsString(date));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue