Spring Boot - 如何为 "java.time.LocalDateTime" 类创建自定义序列化

3

我开发了一个使用Spring Boot的REST服务。我想返回一个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,
. . . 
}

3
那不应该是您首选的格式。如果您将时间存储为毫秒数,则必须同时知道时区才能正确地反序列化它,因为给定的毫秒数可以解释为许多不同的LocalDateTime。如果它真的是一个LocalDateTime,请以与时区无关的格式进行存储;如果它真的是一瞬间的时间,请表示为时间点。 - Andy Turner
你不能只使用java.util.Date吗?因为它将时间存储在毫秒中。@jhontonini - Madhu Bhat
我之前只回答了自定义序列化器的使用,现在添加了时间转换。 - GolamMazid Sajib
3个回答

6

使用@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()+"");
}
}

4

如果您不想使用 @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


我的示例不是转换为毫秒,而是转换为Epoch Unix时间戳。 - Jonas Pedersen

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

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

它以毫秒为单位给出日期。将其格式化为所需的输出是应用程序层的责任。不要在实体本身上使用某些注释进行操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接