How to serialize Joda DateTime with Jackson JSON processor?

Viewed 158357

How do I get Jackson to serialize my Joda DateTime object according to a simple pattern (like "dd-MM-yyyy")?

I've tried:

@JsonSerialize(using=DateTimeSerializer.class)
private final DateTime date;

I've also tried:

ObjectMapper mapper = new ObjectMapper()
    .getSerializationConfig()
    .setDateFormat(df);

Thanks!

10 Answers

Use Built-in Joda Serializer/Deserializer for easy config

If you want custom formatting, there's no need to write a custom Serializer or Deserializer. jackson-datatype-joda 2.x provides a DateTimeSerializer and DateTimeDeserializer on which you can set a DateTimeFormatter to use, providing you custom formatting. You then add the configured Serializer and/or Deserializer to the JodaModule when you add the module.

An advantage of using the provided Serializer/Deserializer (over custom ones) is that you can annotated any DateTime properties with @JsonFormat(pattern = ". . .") to override the format you configure. The custom Serializers/Deserializers shown in most of the other answers (from the Jackson 1.x days) will not honor @JsonFormat annotations. So if you have that one odd ball DateTime value that needs a a different format, it is easily handled, as shown in the below examples.

In addition to the DateTimeSerializer and DateTimeDeserializer, there are others such as LocalDateSerializer/LocalDateDeserializer, PeriodSerializer/PeriodDeserializer, etc.

Examples

Below is a Java and a Kotlin example. You will need to add the following to your dependencies:

com.fasterxml.jackson.datatype:jackson-datatype-joda:{version}

The examples show setting a default custom format, and overriding that format on a per property basis via the @JsonFormat annotation.

Java Example

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.fasterxml.jackson.datatype.joda.cfg.JacksonJodaDateFormat;
import com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer;
import com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer;
import org.joda.time.DateTime;
import org.joda.time.ReadableInstant;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;



public class JacksonJodaTimeJavaExample
{
    private static final DateTimeFormatter DATE_TIME_FORMATTER =
        DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ");
    private static final JacksonJodaDateFormat JACKSON_JODA_DATE_FORMAT =
        new JacksonJodaDateFormat(DATE_TIME_FORMATTER);

    private static ObjectMapper mapper = createMapper();

    private static ObjectMapper createMapper()
    {
        return JsonMapper
            .builder()
            .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
            .addModule(new JodaModule()
                           // If you do not want to customize the formatting, you can remove the next two lines
                           .addSerializer(new DateTimeSerializer(JACKSON_JODA_DATE_FORMAT))
                           .addDeserializer(ReadableInstant.class, new DateTimeDeserializer(ReadableInstant.class, JACKSON_JODA_DATE_FORMAT))
            )
            // Enable pretty printing for our example
            .enable(SerializationFeature.INDENT_OUTPUT)
            .build();
    }

    record Event(
        DateTime startTime,
        DateTime endTime,
        @JsonFormat(pattern = "yyyy-MM-dd 'at' HH:mm:ss")
        DateTime dateTimeInAlternateFormat
    ) {}


    public static void main(String[] args) throws Exception
    {
        final DateTime now = DateTime.now();
        Event event = new Event(now, now.plusHours(1), now);

        String json = mapper.writeValueAsString(event);
        System.out.println(json);

        Event deserializedEvent = mapper.readValue(json, Event.class);
        System.out.println(deserializedEvent);
    }
}

Kotlin Example

import com.fasterxml.jackson.annotation.JsonFormat
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.datatype.joda.JodaModule
import com.fasterxml.jackson.datatype.joda.cfg.JacksonJodaDateFormat
import com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer
import com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer
import org.joda.time.DateTime
import org.joda.time.ReadableInstant
import org.joda.time.format.DateTimeFormat

object JacksonJodaTimeKotlinExample
{
    private val DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZZ")
    private val JACKSON_JODA_DATE_FORMAT = JacksonJodaDateFormat(DATE_TIME_FORMATTER)
    private val mapper = createMapper()

    private fun createMapper() =
        JsonMapper
        .builder()
        .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
        .addModule(
            // If you do not want to customize the formatting, you can remove the "apply" block
            JodaModule().apply {
                addSerializer(DateTimeSerializer(JACKSON_JODA_DATE_FORMAT))
                addDeserializer(ReadableInstant::class.java, DateTimeDeserializer(ReadableInstant::class.java, JACKSON_JODA_DATE_FORMAT))
            })
        // Enable pretty printing for our example
        .enable(SerializationFeature.INDENT_OUTPUT)
        .build()

    data class Event(
        var startTime: DateTime? = null,
        var endTime: DateTime? = null,
        // If we want a DateTime in an alternate format, we can
        @JsonFormat(pattern = "yyyy-MM-dd 'at' HH:mm:ss")
        var dateTimeInAlternateFormat: DateTime? = null)

    fun runExample()
    {
        val now = DateTime.now()
        val event = Event(now, now.plusHours(1), now)
        val json = mapper.writeValueAsString(event)
        println(json)
        val deserializedEvent = mapper.readValue(json, Event::class.java)
        println(deserializedEvent)
    }
}

fun main()
{
    JacksonJodaTimeKotlinExample.runExample()
}
Related