Jackson @JsonFormat 将日期设置为少一天

Jackson @JsonFormat set date with one day less

我已经在我的项目中使用 Spring Date Rest with Spring Boot。 这个项目有一个对象,我使用了注释@JsonFormat 来格式化将从我的 Json 接收的日期字段。 字段 Date 的格式为 "dd/MM/yyyy"。 当我发送 json 值“08/07/1980”时,Jackson 将其转换为值“07/07/1980”。

问题是@Json格式设置的日期少了一天

这是我的源代码

@Temporal(TemporalType.DATE)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy", locale = "pt-BR", timezone = "UTC")
private Date birthDate;

谢谢

使用这个解决方案,它比我的解决方案更有效、更现代:

谢谢@Benjamin Lucidarme。

我使用以下方法解决了我的问题:

@Temporal(TemporalType.DATE)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy", locale = "pt-BR", timezone = "Brazil/East")
private Date birthDate;

我将时区更改为 "Brazil/East" 或 "America/Sao_Paulo",现在正在工作

谢谢

@William 的回答有效,但您应该将这些行添加到您的 application.properties 文件中:

spring.jackson.time-zone=Brazil/East
spring.jackson.locale=pt-BR

这样,您只需填写一次时区和地区,它适用于您申请的所有日期。

我会将 ObjectMapper 时区设置为默认 JVM 时区:

    ObjectMapper objectMapper = new ObjectMapper();
    //Set default time zone as JVM timezone due to one day difference between original date and formatted date.
    objectMapper.setTimeZone(TimeZone.getDefault());

如果您不知道服务器环境使用的时区,这是一个更好的解决方案。

spring-boot 环境中,您可以覆盖默认值 JacksonAutoConfiguration:

@Bean
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
    return builder.createXmlMapper(false)
            // Set timezone for JSON serialization as system timezone
            .timeZone(TimeZone.getDefault())
            .build();
}

在双方(客户端 - 服务器)上注释您的归档日期:

@JsonDeserialize(using = JsonDateDeserializer.class)
@JsonSerialize(using = JsonDateSerializer.class)
private Date birthDate;

并且在两侧再次放置用于序列化和反序列化的实现:

public class JsonDateSerializer extends JsonSerializer<Date> {
    SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");

    @Override
    public void serialize(final Date date, final JsonGenerator gen, final SerializerProvider provider) throws IOException, JsonProcessingException {

        String dateString = format.format(date);
        gen.writeString(dateString);
    }

}


public class JsonDateDeserializer extends JsonDeserializer<Date> {

    SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");

    @Override
    public Date deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException {
        if (jp.getCurrentToken().equals(JsonToken.VALUE_STRING)) {
            try {
                Date date = format.parse(jp.getText().toString());
                return date;
            } catch (ParseException e) {
                //e.printStackTrace();
            }
        }
        return null;
    }

}

我也遇到过类似的问题。我想为这个问题添加的所有答案都是针对上述问题的,我的解决方案将解释问题并提供通用解决方案。

当您对同一个 Date 使用 2 个不同的时区时,您可能会遇到这个问题。 当您执行 new Date() 时,除非您明确指定时区,否则它会使用您的默认时区。让我用代码片段向您解释一下,(您在印度,当前日期是 (9/5/2021, 12 a.m.IST)

// 09/05/2021 00:00:00 IST
Date birthDate = new Date();

现在,当在 birthDate 上方设置模型并使用 JsonFormat 序列化时。默认情况下 JsonFormat 使用 UTC 时区。

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy")
private Date birthDate;

序列化将导致 08/05/2021,而不是 09/05/2021
让我写下 08/05/2021 UTC09/05/2021 IST 时区的日期。
让我也为日期 08/05/2021 18:30:00 UTC09/05/2021 00:00:00 IST 添加时间。
如果您看到日期正确,但时区不同,现在您明白了为什么会这样。有两种方法可以解决这个问题,

  1. 使用相同的时区
  2. 在序列化日期时也添加时间和时区。喜欢 08/05/2021 18:30:00 UTC,和 09/05/2021 00:00:00 IST