如何使用 objectMapper 为 java.time.Instant 设置字符串格式? [英] How to set format of string for java.time.Instant using objectMapper?

查看:36
本文介绍了如何使用 objectMapper 为 java.time.Instant 设置字符串格式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 java.time.Instant 的实体,用于创建数据字段:

I have an entity with java.time.Instant for created data field:

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Item {
    private String id;
    private String url;
    private Instant createdDate;
}

我正在使用 com.fasterxml.jackson.databind.ObjectMapper 将项目以 JSON 格式保存到 Elasticsearch:

I am using com.fasterxml.jackson.databind.ObjectMapper to save item to Elasticsearch as JSON:

bulkRequestBody.append(objectMapper.writeValueAsString(item));

ObjectMapper 将此字段序列化为对象:

ObjectMapper serializes this field as an object:

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

我正在尝试注释 @JsonFormat(shape = JsonFormat.Shape.STRING) 但它对我不起作用.

I was trying the annotation @JsonFormat(shape = JsonFormat.Shape.STRING) but it doesn't work for me.

我的问题是如何将此字段序列化为 2010-05-30 22:15:52 字符串?

My question is how I could serialize this field as 2010-05-30 22:15:52 string?

推荐答案

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

One solution is to use jackson-modules-java8. Then you can add a JavaTimeModule to your object mapper:

ObjectMapper objectMapper = new ObjectMapper();

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

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

By default the Instant is serialized as the epoch value (seconds and nanoseconds in a single number):

{"createdDate":1502713067.720000000}

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

You can change that by setting in the object mapper:

objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

这将产生输出:

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

以上两种格式均已反序列化,无需任何额外配置.

Both formats above are deserialized without any additional configuration.

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

To change the serialization format, just add a JsonFormat annotation to the field:

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

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

You need to set the timezone, otherwise the Instant can't be serialized properly (it throws an exception). The output will be:

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

<小时>

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


Another alternative, if you don't want to (or can't) use java8 modules, is to create a custom serializer and deserializer, using a java.time.format.DateTimeFormatter:

public class MyCustomSerializer extends JsonSerializer<Instant> {

    private DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC);

    @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").withZone(ZoneOffset.UTC);

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

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

Then you annotate the field with those custom classes:

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

输出将是:

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

<小时>

一个细节是,在序列化字符串中,您丢弃了秒的小数部分(小数点后的所有内容).因此,在反序列化时,此信息无法恢复(将设置为零).


One detail is that in the serialized string you're discarding the fraction of second (everything after the decimal point). So, when deserializing, this information can't be recovered (it'll be set to zero).

上例中,原Instant2017-08-14T12:17:47.720Z,但序列化后的字符串为2017-08-1412:17:47(没有秒的分数),所以当反序列化时,结果 Instant2017-08-14T12:17:47Z(.720 毫秒丢失).

In the example above, the original Instant is 2017-08-14T12:17:47.720Z, but the serialized string is 2017-08-14 12:17:47 (without the fraction of seconds), so when deserialized the resulting Instant is 2017-08-14T12:17:47Z (the .720 milliseconds are lost).

这篇关于如何使用 objectMapper 为 java.time.Instant 设置字符串格式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆