2017-02-26 104 views
4

我試圖獲取含有ISO格式的時間戳這樣的迴應:與ObjectMapper + JavaTimeModule註冊JacksonJsonProvider澤西島2客戶端

{ 
... 
    "time" : "2014-07-02T04:00:00.000000Z" 
... 
} 

ZonedDateTime場在我的域模型對象。如果我使用的解決方案在下面的代碼片段中有所評論,最終它可以正常工作。有許多類似的問題,但我希望得到具體的答案 另一種使用JacksonJsonProviderObjectMapper + JavaTimeModule的方法有什麼問題?

 ObjectMapper mapper = new ObjectMapper(); 
     mapper.registerModule(new JavaTimeModule()); 
     JacksonJsonProvider provider = new JacksonJsonProvider(mapper); 
     Client client = ClientBuilder.newBuilder() 
//    .register(new ObjectMapperContextResolver(){ 
//     @Override 
//     public ObjectMapper getContext(Class<?> type) { 
//      ObjectMapper mapper = new ObjectMapper(); 
//      mapper.registerModule(new JavaTimeModule()); 
//      return mapper; 
//     } 
//    }) 
       .register(provider) 
       .register(JacksonFeature.class) 
       .build(); 

錯誤,我得到:

javax.ws.rs.client.ResponseProcessingException: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.ZonedDateTime: no String-argument constructor/factory method to deserialize from String value ('2017-02-24T20:46:05.000000Z') 
at [Source: org.glassfish.jersey.me[email protected]53941c2f 

項目依賴關係:

compile 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.8.7' 
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.7' 
compile 'com.fasterxml.jackson.core:jackson-core:2.8.7' 
compile 'com.fasterxml.jackson.core:jackson-databind:2.8.7' 
compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.7' 
compile 'org.glassfish.jersey.core:jersey-client:2.25.1' 

編輯

反序列化發生在這裏:

CandlesResponse<BidAskCandle> candlesResponse = webTarget.request() 
       .header(HttpHeaders.AUTHORIZATION,"Bearer "+token) 
       .accept(MediaType.APPLICATION_JSON) 
       .get(new GenericType<CandlesResponse<BidAskCandle>>(){}); 

回答

3

如果我使用在以下代碼段中評論的解決方案,它最終會起作用。

首先,您在列表中缺少依賴關係,您也有問題,這是問題所在。

jersey-media-json-jackson

此模塊取決於具有JacksonJsonProvider本地傑克遜模塊上。當您註冊JacksonFeaturejersey-media-json-jackson附帶)時,它會註冊自己的JacksonJaxbJsonProvider,這似乎優先於您提供的任何東西。

當您使用ContextResolver時,JacksonJsonProvider實際上查找ContextResolver並使用它來解析ObjectMapper。這就是它工作的原因。無論您使用JacksonFeature還是註冊了自己的JacksonJsonProvider(未配置ObjectMapper),ContextResovler都可以使用。

關於jersey-media-json-jackson模塊的另一件事,它參與了Jersey的auto-discoverable機制,該機制註冊了它的JacksonFeature。所以即使你沒有明確註冊,它仍然會被註冊。唯一的方法,以避免它被註冊的是:

  1. 禁用自動發現(如上面所提到的previous link
  2. 不要使用jersey-media-json-jackson。只需使用傑克遜本地模塊jackson-jaxrs-json-provider即可。關於這一點,雖然是,jersey-media-json-jackson增加了本地模塊頂部的幾個功能,所以你會失去這些。
  3. 還沒有測試,但似乎如果您使用JacksonJaxbJsonProvider而不是JacksonJsonProvider,它可能會工作。如果您查看source for the JacksonFeature,您會看到它檢查已註冊的JacksonJaxbJsonProvider。如果有的話,它不會註冊它自己的。

    我不確定這件事的一件事是自動發現。註冊的順序,如果它會影響您是否註冊您的註冊JacksonJaxbJsonProvider。你可以測試的東西。 。

+1

中添加了我選擇了'JacksonJaxbJsonProvider'選項,因爲它看起來更直接,並且不涉及額外的依賴關係。 –

1

傑克遜配置看起來不錯,我嘗試以下,並能夠反序列化值:

public class Test { 

    public static void main(String[] args) throws Exception { 
     ObjectMapper mapper = new ObjectMapper(); 
     mapper.registerModule(new JavaTimeModule()); 
     Model model = mapper.readValue("{\"time\" : \"2014-07-02T04:00:00.000000Z\"}", Model.class); 
     System.out.println(model.getTime()); 
    } 

} 

class Model{ 
    private ZonedDateTime time; 

    public ZonedDateTime getTime() { 
     return time; 
    } 
    public void setTime(ZonedDateTime time) { 
     this.time = time; 
    } 
} 

我可以通過註釋掉mapper.registerModule(new JavaTimeModule());重現。所以,它看起來像平針織客戶端不使用自定義mapper實例。您可以嘗試按照here所述進行配置。

+0

試過了,沒有變化:( –

+0

@ libnull-dev的我已經更新了答案 –

+0

你的意思是這個'Ob​​jectMapper映射器=新ObjectMapper();?mapper.registerModule(新JavaTimeModule()); JacksonJsonProvider提供商= new JacksonJsonProvider(); provider.setMapper(mapper); ClientConfig config = new ClientConfig(provider); Client client = ClientBuilder.newClient(config);'然而這也不起作用 –