0

I have an OffsetDateTime. With Jackson in json i see this value:

2021-03-01T22:21:02.8624372-05:00

On the field I use

@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ssZ")

this value is displayed

2021-03-01T22:21:02-0500

Any idea to get

2021-03-01T22:21:02-05:00
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
robert trudel
  • 5,283
  • 17
  • 72
  • 124

3 Answers3

1

I had a similar issue with Instant. There I had overridden the Instant serializer of the JavaTimeModule and used a custom DateTimeFormatter like this:

ObjectMapper objectMapper = new ObjectMapper();
        
DateTimeFormatter instantFormatter = new DateTimeFormatterBuilder()
    .appendInstant(0)
    .toFormatter();
        
JavaTimeModule jtm = new JavaTimeModule();
jtm.addSerializer(Instant.class, new JsonSerializer<Instant>() {
    @Override
    public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        gen.writeString(instantFormatter.format(value));
    }
});

objectMapper.registerModule(jtm);

But you should also be able to use @JsonSerialize on that particular field instead of @JsonFormat:

@JsonSerialize(using = MyCustomSerializer.class)
OffsetDateTime problematicField;

DateTimeFormatterBuilder lets you easily customize your format

Benjamin M
  • 23,599
  • 32
  • 121
  • 201
-1

Assuming you're already using the JavaTimeModule (with WRITE_DATES_AS_TIMESTAMPS as false that produces the output in your first snippet), you simply need to provide an appropriate date pattern in the @JsonFormat. For example,

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssZZZZZ")

where pattern is

Datatype-specific additional piece of configuration that may be used to further refine formatting aspects. This may, for example, determine low-level format String used for java.util.Date serialization; however, exact use is determined by specific JsonSerializer

The "Datetype-specific" here is a serializer for JsonSerializer. Since you're using JavaTimeModule (assuming!!!), that's OffsetDateTimeSerializer. That @JsonFormat pattern is interpreted as a DateTimeFormatter pattern which states

Offset Z: This formats the offset based on the number of pattern letters. One, two or three letters outputs the hour and minute, without a colon, such as '+0130'. The output will be '+0000' when the offset is zero. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
-1

Well there are so many ways it can be done, Below code shows simple 2 ways:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

public class JsonDateFormat {

    /*
     * Approach I
     */
    @SuppressWarnings("static-method")
    public String getCurrentDateTime() {
        return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.now());
    }

    /*
     * Approach II
     */
    @SuppressWarnings("static-method")
    @JsonSerialize(using = CustomDateTimeFormatter.class)
    public Date getCustomCurrentDateTime() {
        return new Date();
    }

    public static void main(final String[] args) throws JsonProcessingException {
        final JsonDateFormat jsonDateFormat = new JsonDateFormat();
        final String result = new ObjectMapper().writeValueAsString(jsonDateFormat);
        System.out.println(result);
    }

}

Below is custom field serilizer.

import java.io.IOException;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

public class CustomDateTimeFormatter extends StdSerializer<Date> {

    private static final long serialVersionUID = 1L;

    public CustomDateTimeFormatter() {
        this(null);
    }

    public CustomDateTimeFormatter(final Class<Date> t) {
        super(t);
    }

    @Override
    public void serialize(final Date date, final JsonGenerator jgen, final SerializerProvider provider) throws IOException {
        final String dateTime = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(OffsetDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
        jgen.writeObject(dateTime);
    }

}

Lastly, you could also use custom DateTimeFormatter. See Reference DateTimeFormatter doesn't parse custom date format

Pratiyush Kumar Singh
  • 1,977
  • 3
  • 19
  • 39