読者です 読者をやめる 読者になる 読者になる

Jackson で OffsetDateTime を ISO8601 形式にシリアライズする

java

JavaTimeModule を使って シリアライズする場合に OffsetDateTime などが変な数字になる場合がある。

@Data
class MyObject {
    @JsonProperty("datetime")
    private OffsetDateTime dateTime;
}

ObjectMapper mapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());

MyObject paramObject = new MyObject();
paramObject.setDateTime(OffsetDateTime.now());

Map<String, String> map = objectMapper.convertValue(paramObject, new TypeReference<Map<String, String>>() {});

map.get("datetime"); // ここがタイムスタンプになる

下記のようにシリアライズされる際に WRITE_DATES_AS_TIMESTAMPS かどうかを確認している箇所がある。

https://github.com/FasterXML/jackson-datatype-jsr310/blob/jackson-datatype-jsr310-2.8.4/src/main/java/com/fasterxml/jackson/datatype/jsr310/ser/InstantSerializerBase.java#L81

https://github.com/FasterXML/jackson-datatype-jsr310/blob/jackson-datatype-jsr310-2.8.4/src/main/java/com/fasterxml/jackson/datatype/jsr310/ser/JSR310FormattedSerializerBase.java#L165...L174

https://github.com/FasterXML/jackson-databind/blob/jackson-databind-2.8.4/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java#L162...L184

ObjectMapper がデフォルトで WRITE_DATES_AS_TIMESTAMPS が有効になっているのでこれを解除する。

@Data
class MyObject {
    @JsonProperty("datetime")
    private OffsetDateTime dateTime;
}

ObjectMapper mapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

MyObject paramObject = new MyObject();
paramObject.setDateTime(OffsetDateTime.now());

Map<String, String> map = objectMapper.convertValue(paramObject, new TypeReference<Map<String, String>>() {});

map.get("datetime"); // ISO8601 形式の文字列となる