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

查看:303
本文介绍了如何使用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-14 12:17:47(不包括秒数),因此在反序列化时,生成的Instant2017-08-14T12:17:47Z(毫秒丢失).

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天全站免登陆