2017-08-13 73 views
1

我有java.time.Instant用於創建數據字段的實體:如何使用objectMapper爲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保存項目Elasticsearch爲JSON:

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

ObjectMapper連載這個領域作爲一個對象:

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

我在嘗試註釋@JsonFormat(shape = JsonFormat.Shape.STRING),但它不適用於我。

我的問題是我如何能夠序列化這個字段爲2010-05-30 22:15:52字符串?

+0

https://github.com/FasterXML/jackson-modules-java8/tree/master/datetime –

+0

@JBNizet謝謝你的回答,我已經添加了'objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);''和' objectMapper.findAndRegisterModules()'它不適用於我。 –

+0

您是否已將模塊jar文件添加到類路徑中? –

回答

2

一種解決方案是使用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 = "UTC") 
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").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())); 
    } 
} 

然後你註釋字段與自定義類:

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

輸出將是:

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

其中的一個細節是,在序列化的字符串你丟棄(小數點後的所有內容)第二的部分。所以,在反序列化時,這些信息無法恢復(它將被設置爲零)。

在上面的例子中,原始Instant2017-08-14T12:17:47.720Z,但序列化的字符串是2017-08-14 12:17:47(沒有秒的分數),所以反序列化時所得到的是Instant2017-08-14T12:17:47Z(所述.720毫秒丟失)。

+0

如果我想保持幾秒鐘的時間,我將不得不使用什麼格式的字符串?謝謝。 –

0

您需要添加下面的依賴

<dependency> 
    <groupId>com.fasterxml.jackson.datatype</groupId> 
    <artifactId>jackson-datatype-jsr310</artifactId> 
    <version>2.6.5</version> 
</dependency> 

,然後註冊模塊如下:

ObjectMapper objectMapper = new ObjectMapper(); 
objectMapper.findAndRegisterModules(); 
+0

謝謝,我發現了此解決方案。但是,這個解決方案似乎被棄用 –

+0

看看這裏:http://www.baeldung.com/jackson-serialize-dates –

相關問題