【问题标题】:Spring Boot - How to create a custom serialization for " java.time.LocalDateTime" classSpring Boot - 如何为“java.time.LocalDateTime”类创建自定义序列化
【发布时间】:2019-01-05 11:41:12
【问题描述】:

我用 Spring Boot 开发了一个休息服务。我想以毫秒为单位返回用户生日的 json 响应。 如何将java.time.LocalDateTime 对象序列化到毫秒?

我的模型课:

    @Entity(name = "users")
    public class User implements Serializable {

        @Id
        @GeneratedValue
        @Column(name = "user_id")
        private Long id;

        @Column(name = "first_name")
        private String firstName;

        @Column(name = "last_name")
        private String lastName;



        @Column(name = "date_of_birth")
        private LocalDateTime dateOfBirth;  

 . . .

    }

目前的回应:

{
 . . .
"dateOfBirth":[2018,7,25,7,0],
. . . 
}

首选回复:

{
 . . .
"dateOfBirth": 1532786354419,
. . . 
}

【问题讨论】:

  • 这应该是您的首选格式。如果您存储为毫秒,您还必须知道时区才能正确反序列化它,因为给定的毫秒可以解释为许多不同的 LocalDateTimes。如果真的是 LocalDateTime,则以独立于时区的格式存储;如果它真的是一个瞬间,将它表示为一个瞬间。
  • 你不能只使用 java.util.Date 代替,因为它以毫秒存储它吗? @jhontonini
  • 我只回答了使用自定义序列化程序。现在添加时间转换

标签: java json spring-boot web jackson


【解决方案1】:

使用@JsonSerialize(using = CustomSerializer.class)

@Entity(name = "users")
public class User implements Serializable {

    @Id
    @GeneratedValue
    @Column(name = "user_id")
    private Long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;


    @JsonSerialize(using = CustomSerializer.class)
    @Column(name = "date_of_birth")
    private LocalDateTime dateOfBirth;  

    . . .

}

自定义序列化器类:

public class CustomSerializer extends JsonSerializer<LocalDateTime> {
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
    //add your custom date parser
    gen.writeString(value.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()+"");
}
}

【讨论】:

    【解决方案2】:

    如果您不想用@JsonSerialize 装饰所有对象,您可以将对象映射器配置为始终为LocalDateTime 返回一个long。

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateSerializer());
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateDeserializer());
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }
    

    以及反序列化器。

    public class LocalDateSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            gen.writeString(String.valueOf(value.atZone(ZoneId.systemDefault()).toEpochSecond()));
        }
    }
    
    public class LocalDateDeserializer extends JsonDeserializer<LocalDateTime> {
        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            return LocalDateTime.ofInstant(Instant.ofEpochSecond(Long.parseLong(p.getValueAsString())), ZoneId.systemDefault());
        }
    }
    

    在您的示例中,您使用的出生日期可能是LocalDate

    【讨论】:

    • 我的示例没有转换为 Mills,而是转换为 Epoch Unix Time Stamp。
    【解决方案3】:

    为什么不存储日期属性如下:

    @Temporal(TemporalType.TIMESTAMP)
    private Date date = new Date();
    

    它以毫秒为单位给出日期。将其格式化为所需的输出是应用层的责任。不要在带有注释的实体本身上这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-30
      • 2018-07-21
      • 2016-12-31
      • 2021-11-29
      • 2019-01-01
      • 2012-12-27
      • 2019-11-27
      相关资源
      最近更新 更多