我正在爲REST端點製作serivce客戶端,使用JAX-RS客戶端進行HTTP請求,並使用傑克遜對(序列化)JSON實體。爲了處理JSR-310(Java8)日期/時間對象,我將com.fasterxml.jackson.datatype:jackson-datatype-jsr310
模塊作爲依賴項添加到服務客戶端,但我沒有得到它的工作。JAX-RS客戶端對Java8日期/時間的傑克遜(德)序列化
如何配置JAX-RS和/或Jackson使用jsr310模塊?
我用下面的依賴關係:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>${jax-rs.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
我不想讓服務客戶端(被釋放庫)依賴於任何特定的實現 - 新澤西州一樣,所以我只能依靠JAX-RS API。運行我的集成測試我說:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
的JAX-RS客戶端的實例化是在工廠對象來完成,如下所示:
import javax.ws.rs.Produces;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
@Produces
public Client produceClient() {
return ClientBuilder.newClient();
}
一個典型的DTO是這樣的:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import java.time.Instant;
import static java.util.Objects.requireNonNull;
@JsonPropertyOrder({"n", "t"})
public final class Message {
private final String name;
private final Instant timestamp;
@JsonCreator
public Message(@JsonProperty("n" final String name,
@JsonProperty("t" final Instant timestamp) {
this.name = requireNonNull(name);
this.timestamp = requireNonNull(timestamp);
}
@JsonProperty("n")
public String getName() {
return this.name;
}
@JsonProperty("t")
public Instant getTimestamp() {
return this.timestamp;
}
// equals(Object), hashCode() and toString()
}
的請求做過這樣的:
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
public final class Gateway {
private final WebTarget endpoint;
public Message postSomething(final Something something) {
return this.endpoint
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.json(something), Message.class);
}
// where Message is the class defined above and Something is a similar DTO
}
JSON序列化和反序列化工作正常的字符串,整型,BigIntegers,列表等。然而,當我做這樣的事情在我的測試System.out.println(gateway.postSomthing(new Something("x", "y"));
我得到以下異常:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.Instant` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('Fri, 22 Sep 2017 10:26:52 GMT')
at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 1, column: 562] (through reference chain: Message["t"])
at org.example.com.ServiceClientTest.test(ServiceClientTest.java:52)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of `java.time.Instant` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('Fri, 22 Sep 2017 10:26:52 GMT')
at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 1, column: 562] (through reference chain: Message["t"])
at org.example.com.ServiceClientTest.test(ServiceClientTest.java:52)
從中我得出結論,傑克遜沒有按不知道如何將字符串反序列化爲Instants。我發現了關於這個主題的博客和SO問題,但是我沒有找到關於如何使其工作的明確解釋。
請注意,我希望服務客戶端處理日期字符串,如"Fri, 22 Sep 2017 10:26:52 GMT"
以及"2017-09-22T10:26:52.123Z"
,但我希望它始終序列化爲ISO 8601日期字符串。
誰可以解釋如何使反序列化成Instant
工作?
如果JavaTimeModule未在ObjectMapper中註冊,通常會發生這種情況:https://github.com/FasterXML/jackson-modules-java8#user-content-registering-modules –
@Hugo我讀到了這個,但我不清楚如何做這個註冊。你能否將這一切歸結爲答案? – Rinke
我從來沒有同時使用澤西和傑克遜,所以不知道如何去做。我通常以編程方式設置ObjectMapper(如前面評論中提供的鏈接)。無論如何,也許這可以幫助:https://stackoverflow.com/q/18872931/7605325 –