如何使用objectMapper设置java.time.Instant的字符串格式?

  1. 我有一个带有 java.time.Instant的实体用于创建的数据字段:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Item {
    private String id;
    private String url;
    private Instant createdDate;
}

我使用com.fasterxml.jackson.databind.ObjectMapper将项目保存为JSON格式,ObjectMapper将此字段序列化为对象:

"createdDate": {
    "epochSecond": 1502643595,
    "nano": 466000000
}

一种解决方案是使用 jackson-modules-java8.然后您可以将JavaTimeModule添加到对象映射器:

ObjectMapper objectMapper = new ObjectMapper();

JavaTimeModule module = new JavaTimeModule();
objectMapper.registerModule(module);

默认情况下,Instant被序列化为纪元值(单个数字中的秒和纳秒):

{"createdDate":1502713067.720000000}

您可以通过在对象映射器中设置来更改它:

objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

这将产生输出:

{"createdDate":"2017-08-14T12:17:47.720Z"}

上述两种格式都是反序列化的,无需任何其他配置.

要更改序列化格式,只需在字段中添加JsonFormat注释:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Instant createdDate;

您需要设置时区,否则Instant无法正确序列化(它会引发异常).输出将是:

{"createdDate":"2017-08-14 12:17:47"}

如果您不想(或不能)使用java8模块,另一种方法是使用java.time.format.DateTimeFormatter创建自定义序列化程序和反序列化程序:

public class MyCustomSerializer extends JsonSerializer<Instant> {

    private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") .withLocale(Locale.getDefault())
            .withZone(ZoneId.systemDefault());

    @Override
    public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        String str = fmt.format(value);

        gen.writeString(str);
    }
}

public class MyCustomDeserializer extends JsonDeserializer<Instant> {

    private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") .withLocale(Locale.getDefault())
            .withZone(ZoneId.systemDefault());

    @Override
    public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        return Instant.from(fmt.parse(p.getText()));
    }
}

然后使用这些自定义类注释该字段:

@JsonDeserialize(using = MyCustomDeserializer.class)
@JsonSerialize(using = MyCustomSerializer.class)
private Instant createdDate;

输出将是:

{"createdDate":"2017-08-14 12:17:47"}

一个细节是,在序列化字符串中,您将丢弃秒的小数部分(小数点后的所有内容).因此,在反序列化时,此信息无法恢复(它将被设置为零).
在上面的例子中,原始的Instant是2017-08-14T12:17:47.720Z,但是序列化的字符串是2017-08-14 12:17:47(没有秒的分数),所以当反序列化时产生的Instant是2017-08-14T12:17:47Z(丢失.720毫秒).

### Spring Boot 中使用 YAML 配置时间格式的方法 在 Spring Boot 应用程序中,可以通过自定义 `ObjectMapper` 来实现日期时间格式的全局配置。以下是基于 YAML 文件配置时间和日期格式的具体方法。 #### 方法一:通过自定义 `ObjectMapper` 可以创建一个配置类来覆盖默认的 Jackson `ObjectMapper` 实现,并指定所需的日期时间格式: ```java @Configuration public class WebConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); JavaTimeModule module = new JavaTimeModule(); objectMapper.registerModule(module); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")); return objectMapper; } } ``` 在此示例中,设置了日期时间为 ISO 8601 格式字符串表示形式[^4]。 #### 方法二:通过 YAML 配置文件设置全局日期时间格式 如果希望直接在 YAML 文件中完成日期时间格式的配置,可以在 `application.yml` 或特定环境下的 YAML 文件中添加如下内容: ```yaml spring: jackson: date-format: yyyy-MM-dd'T'HH:mm:ss.SSSZ time-zone: UTC ``` 上述配置将全局应用到所有的 JSON 序列化和反序列化操作中,确保所有的时间字段都遵循指定的格式[^2]。 #### 方法三:针对不同环境分别配置 对于多环境部署场景,可以利用 YAML 的多文档特性,在不同的环境中设置不同的日期时间格式。例如: ```yaml server: port: 8080 spring: profiles: default jackson: date-format: yyyy-MM-dd HH:mm:ss --- server: port: 8081 spring: profiles: dev jackson: date-format: yyyy-MM-dd'T'HH:mm:ss.SSSZ --- server: port: 8082 spring: profiles: prod jackson: date-format: yyyy-MM-dd ``` 这样可以根据激活的不同 profile 使用相应的日期时间格式。 #### 特殊情况处理 需要注意的是,某些情况下可能涉及时区信息的处理。例如,当传入的分片键为 `java.time.Instant` 类型时,系统可能会自动附加本地时区信息并将其转换为目标格式。因此建议在设计数据交互逻辑时充分考虑时区的影响[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值