Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize java.time.localdate into json using Jackson

I'm writing a Java 8 Spring MVC application that communicates with a legacy Progress OpenEdge application using a REST service (I'm using Spring's RestTemplate for this). The data I need to read from and write to the Progress application contains some dates. In the Java application, I use a java.time.LocalDate datatype to represent these fields and I'm using Jackson to serialize / deserialize the data into / from Json.

The problem I'm having is the following. When I send data from the Progress Application, the date is send as '2015-01-02' and stored in my Java entity as a LocalDate as expected. When the data is send to the web front-end the Json also contains the date in the same format. When I change information in the web front-end and apply it, it's also send back to the Java application as '2015-01-02' and again stored as a LocalDate without problems. But when I than send the data onwards to the Progress application, the Json I receive doesn't contain the date as '2015-01-02' but as an array containing three fields (2015.0, 1.0, 2.0) and the Progress application is unable to assign this back to a date field in the database.

Offcourse I could write a conversion on the Progress side to convert the array back into a date, but I'd like to avoid this as I would expect the date to always be send in the ISO 8601 format.

According to the information I find on Jackson, a java.time.LocalDate is represented as an array when WRITE_DATES_AS_TIMESTAMPS is enabled, but I have this disabled (And when the date is send to the web front-end, it's not being send as an array...)

Here is some relevant code:

The CustomObjectMapper:

@Service
public class CustomObjectMapper extends ObjectMapper
{
  public CustomObjectMapper()
  {
    this.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
                   false);
  }
}

The configuration in my servlet.xml

<mvc:annotation-driven>
  <mvc:message-converters>
    <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
      <property name="objectMapper" ref="customObjectMapper"/>
    </bean>
  </mvc:message-converters>
</mvc:annotation-driven>

<bean id="customObjectMapper" class="com.msoft.utility.CustomObjectMapper"/>

The field definition:

@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate deliveryDate;

I'm using Java 8 with Spring 4.1.5 and Jackson 2.5.1.

Any tips how I could get this working or were to search for a solution would be greatly appreciated as I've already been working on this for almost 2 days...

Thanks

EDIT:

Some extra info...

I've included the Jackson JSR-310 module in my pom.xml. Here is the releveant part of my pom file...

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-annotations</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-jsr310</artifactId>
  <version>2.5.1</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>4.1.5.RELEASE</version>
  <scope>test</scope>
  <type>jar</type>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.1.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jpa</artifactId>
  <version>1.7.2.RELEASE</version>
</dependency>

Also, if I understood correctly, Spring will register this module automatically when it's detected. See the info on Jackson2ObjectMapperFactoryBean

Note that Jackson's JSR-310 and Joda-Time support modules will be registered automatically when available (and when Java 8 and Joda-Time themselves are available, respectively).

So I don't think I should have to do anything else to get this working correctly, but obviously I'm still missing something...

like image 308
HeinoVDS Avatar asked Feb 26 '15 14:02

HeinoVDS


2 Answers

This worked for me, and I'm not using Spring boot.

@Configuration
@EnableWebMvc
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
    }
}
like image 120
Niclas Avatar answered Nov 15 '22 21:11

Niclas


I think you just need to register JSR-310 (Java 8 Date/Time) module:

https://github.com/FasterXML/jackson-datatype-jsr310/

since Jackson core can not rely on any Java 8 features (baseline at this point, with 2.5, is Java 6). And going forward support for most datatype libraries will go through plug-in modules anyway.

like image 41
StaxMan Avatar answered Nov 15 '22 19:11

StaxMan