如何使用objectMapper设置java.time.Instant的字符串格式? [英] How to set format of string for java.time.Instant using objectMapper?
问题描述
我有一个带有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).
在上面的示例中,原始的Instant
是2017-08-14T12:17:47.720Z
,但是序列化的字符串是2017-08-14 12:17:47
(不包括秒数),因此在反序列化时,生成的Instant
是2017-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屋!