简体   繁体   English

杰克逊的旧日期 API 和 ZonedDateTime 的 JsonFormat 行为不一致

[英]Inconsistent behaviour of Jackson's JsonFormat for Old Date API and ZonedDateTime

I was trying to use Jackson's JsonFormat annotation in my POJO class to serialize the ZonedDateTime into a different timezone.我试图在我的POJO class 中使用 Jackson 的 JsonFormat 注释将 ZonedDateTime 序列化为不同的时区。 (Say the timezone in ZonedDateTimeZone is ET, I want to serialize it in UTC) (假设 ZonedDateTimeZone 中的时区是 ET,我想将其序列化为 UTC)

My POJO:我的POJO:

package com.example.demo;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;

import java.time.ZonedDateTime;

package com.example.demo;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;

import java.time.ZonedDateTime;

public class POJO {


    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSZ", timezone = "UTC")
    private ZonedDateTime zonedDateTimeWithPatternAndTimeZoneInJsonFormat;

    @JsonFormat(timezone = "UTC")
    private ZonedDateTime zonedDateTimeWithTimeZoneInJsonFormat;

    private ZonedDateTime zonedDateTime;


    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSZ", timezone = "UTC")
    private Date oldDateWithTimeZoneAndPatternInJsonFormat;

    @JsonFormat(timezone = "UTC")
    private Date oldDateWithTimeZoneInJsonFormat;

    private Date oldDate;

    //  getters and setters below


}




Main Method主要方法

package com.example.demo;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.time.*;
import java.util.TimeZone;

package com.example.demo;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

//@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) throws JsonProcessingException {

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.setTimeZone(TimeZone.getDefault());
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        LocalDateTime ldt = LocalDateTime.of(2020, Month.JUNE.getValue(), 12, 15, 0 , 0);
        ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.of("America/New_York"));
        Date oldDate = Date.from(zdt.toInstant());

        System.out.println("old Date with System's time zone" + oldDate);

        POJO pojo = new POJO();
        pojo.setOldDate(oldDate);
        pojo.setOldDateWithTimeZoneAndPatternInJsonFormat(oldDate);
        pojo.setOldDateWithTimeZoneInJsonFormat(oldDate);

        pojo.setZonedDateTimeWithPatternAndTimeZoneInJsonFormat(zdt);
        pojo.setZonedDateTimeWithTimeZoneInJsonFormat(zdt);
        pojo.setZonedDateTime(zdt);

        System.out.println(objectMapper.writeValueAsString(pojo));

    }


}

Output: Output:

old Date with System's time zoneSat Jun 13 00:30:00 IST 2020

{
    "zonedDateTimeWithPatternAndTimeZoneInJsonFormat": "2020-06-12 19:00:00.000+0000",
    "zonedDateTimeWithTimeZoneInJsonFormat": "2020-06-12T15:00:00-04:00",
    "zonedDateTime": "2020-06-12T15:00:00-04:00",
    "oldDateWithTimeZoneAndPatternInJsonFormat": "2020-06-12 19:00:00.000+0000",
    "oldDateWithTimeZoneInJsonFormat": "2020-06-12T19:00:00.000+00:00",
    "oldDate": "2020-06-13T00:30:00.000+05:30"
}

As you can see in output, if i only specify timezone and not pattern, the oldDateWithTimeZone is serialized in UTC timezone but for ZonedDateTime only specifying timezone doesn't serialize it in specified timezone.正如您在 output 中看到的,如果我只指定时区而不指定模式,则 oldDateWithTimeZone 在 UTC 时区中序列化,但对于 ZonedDateTime,仅指定时区不会在指定时区中序列化它。 But if you specify pattern as well, It respects the specified timezone.但是,如果您也指定模式,它会遵守指定的时区。

Seems like it's an issue in jackson-databind.似乎这是 jackson-databind 中的一个问题。 Reported the issue on https://github.com/FasterXML/jackson-databind/issues/2799 .https://github.com/FasterXML/jackson-databind/issues/2799上报告了该问题。

As mentioned in question's comments section, Specifying timezone along with pattern, ie @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss.SSSZ", timezone = "UTC") works as expected.如问题评论部分所述,指定时区和模式,即@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss.SSSZ", timezone = "UTC")按预期工作。 I earlier tried just with timezone.我之前只尝试过时区。

@JsonFormat(timezone= "UTC") sets your timezone when serializing date, not format. @JsonFormat(timezone= "UTC")在序列化日期时设置您的时区,而不是格式。 If you want to change format i suggest using如果你想改变格式我建议使用

@JsonSerialize(using = CustomDateSerializer.class)

With implementation of CustomDateSerializer随着CustomDateSerializer的实施

class CustomDateSerializer extends StdSerializer<ZonedDateTime> {


public CustomDateSerializer(Class<ZonedDateTime> t) {
    super(t);
}

public CustomDateSerializer() {
    this(null);
}

@Override
public void serialize(ZonedDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
    LocalDateTime utc = LocalDateTime.ofInstant(value.toInstant(), ZoneId.of("UTC"));
    gen.writeString("##date format here##");
}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM