2016-01-07 74 views
1

基於這個問題How to get a class instance of generics type T我已經實現了以下類:嵌套泛型參數的方法參數 - Java的

public class OkJsonConverter<T> { 

    final Class<T> typeParameterClass; 

    public OkJsonConverter(Class<T> typeParameterClass) { 
     this.typeParameterClass = typeParameterClass; 
    } 

    protected T processJson(String json) throws OkClientException { 
     T object = null; 
     ObjectMapper objectMapper = new ObjectMapper(); 
     try { 
      JsonNode jsonNode = objectMapper.readTree(json); 

      if (jsonNode.get("error_code") != null) { 
       Error error = objectMapper.treeToValue(jsonNode, Error.class); 
       throw new OkClientException("API returned error", error); 
      } else { 
       object = objectMapper.treeToValue(jsonNode, typeParameterClass); 
      } 
     } catch (IOException e) { 
      throw new OkClientException("unable to process json", e); 
     } 
     return object; 
    } 

} 

我可以使用這個類與一般的參數,例如:

return new OkJsonConverter<User>(User.class).processJson(response.getBody()); 

但現在我正在努力如何使它與這樣一個嵌套的通用參數工作List<Method>

此代碼不起作用:

return new OkJsonConverter<List<Method>>(List<Method>.class).processJson(response.getBody()); 

請幫助改變這段代碼爲了讓它工作。

回答

0

最後,感謝user3707125我已經找到一種方法如何實現這一點:

通過idierL

public class OkJsonConverter { 

private static final String ERROR_CODE_FIELD_NAME = "error_code"; 

protected <T> T readTreeToValue(String json, TypeReference<T> valueTypeRef) throws OkClientException { 
    T object = null; 

    ObjectMapper objectMapper = new ObjectMapper(); 
    try { 
     JsonNode jsonNode = objectMapper.readTree(json); 

     if (jsonNode.has(ERROR_CODE_FIELD_NAME)) { 
      Error error = objectMapper.treeToValue(jsonNode, Error.class); 
      throw new OkClientException("Ok API returned error", error); 
     } else { 
      JavaType type = objectMapper.getTypeFactory().constructType(valueTypeRef); 
      object = objectMapper.convertValue(jsonNode, type); 
     } 
    } catch (IOException e) { 
     throw new OkClientException("Unable to process JSON", e); 
    } 

    return object; 
} 

}

現予以更正,下面的代碼工作正常:

List<Method> result = new OkJsonConverter().readTreeToValue(response.getBody(), new TypeReference<List<Method>>() {}); 
+0

請注意,您的解決方案根本不是類型安全的(如您的'@ SuppressWarnings'所示):即使JSON實際上包含「List 」,也可以工作,並且您只會在運行時注意到它在嘗試操作時在'result'上,當你得到'ClassCastException'。作爲一般規則,不惜一切代價避免此類壓制警告,因爲您幾乎可以保證在某個時候遇到麻煩。 –

+0

感謝您的評論。不幸的是,現在我沒有更好的一個 – alexanoid

+0

其實,有一個...只需用'objectMapper.convertValue(jsonNode,type)'替換未檢查的轉換和'treeToValue'調用。 –

4

Java沒有任何方法將該類型表示爲Class。可以得到的最接近的近似值是(Class<List<Method>>) (Class) List.class,但是這只是表示您只是在查看不知道其元素類型的基本List而已。

不管你的JSON轉換器是否工作,都不清楚,但應該在你使用的轉換器的文檔中指定,它必須自己處理,因爲這是Java中的一個普遍問題當你試圖反思泛型類型時。

+0

感謝您的回答。我試圖將您的建議應用到我的代碼中,但現在沒有任何成功。 – alexanoid

+2

Java有[way](http://gafter.blogspot.com/2006/12/super-type-tokens.html)代表參數化類型,[傑克遜](https://github.com/FasterXML/jackson-core)例如[使用這種技術](https://fasterxml.github.io/jackson-core/javadoc/2.4/com/ fasterxml /傑克遜/型芯/類型/ TypeReference.html)。 – user3707125

+1

@ user3707125,是的,那是真的;這就是爲什麼我澄清「以任何方式將該類型表示爲」Class「。 –