方法是这样的:
protected <T> TestPageResult<T> getTestPageResutForRequest(MockHttpServletRequestBuilder request) throws Exception {
String responseJson = mockMvc.perform(request).andReturn().getResponse()
.getContentAsString();
TestPageResult<T> response = getObjectMapper().readValue(responseJson,
new TypeReference<TestPageResult<T>>() {
});
return response;
}
我这样调用它:
TestPageResult<SomeDto> pageResult = this.<SomeDto>getTestPageResutForRequest(getRequest());
测试页面结果是:
protected static class TestPageResult<T> {
private List<T> items;
private long totalCount = -1;
public TestPageResult() {
}
//omitted getters and setters
}
生成的 pageResult.getItems() 包含 LinkedHashMap 列表,而不是 SomeDto 列表。如果我只是在 objectMapper.readValue 方法中硬编码 SomeDto 类型,我会得到正确的结果。
有什么问题吗?
编辑:建议的重复确实解决了我的问题 - 有点。 我用过:
JavaType type = getObjectMapper().getTypeFactory().constructParametricType(TestPageResult.class, clazz);
TestPageResult<T> response = getObjectMapper().readValue(responseJson, type);
问题是没有办法不将 Class 参数传递给该方法。因此,由于传递泛型类型和与类相同的东西,该方法看起来很丑陋。显然,您现在不能传递泛型,但这样就需要进行强制转换并添加 SuppressWarnings 等。
最佳答案
问题是删除。所有这些<T>
参数在被删除后,不再存在于编译的代码中。这意味着来源 new TypeReference<TestPageResult<T>>()
看起来像 new TypeReference<TestPageResult>()
一旦编译,这不是你想要的。 (类似于 List<String>
在编译代码中最终成为 List
,这只是编译时验证,您不会将 Integer
添加到 String
List
。)
我认为大约有两种方法可以处理这个问题(在本例中),这两种方法您都已经偶然发现了:
- 您可以创建一个能够正确表示您想要的类型,例如:
new TypeReference<TestPageResult<SomeDto>>()
,或class SomeDtoPageResult extends TestPageResult<SomeDto>
然后您可以在readValue(..., SomeDtoPageResult.class)
等地方使用它; - 或者您创建一个完整的类表示,就像您对
JavaType
所做的那样
你真正想要的东西不会实现。最好的选择是修补并提出解决该问题的最简洁的代码。泛型可以让你表达非常复杂的结构,当你序列化一个实际的实例(嵌套对象)时,结果很好,但是当类需要在运行时进行内省(introspection)时,例如对于反序列化(您的用例)或构建模型(例如生成 Swagger 文档),这会成为问题。
关于java - 在泛型方法中传递类型时,使用 TypeReference 的 ObjectMapper 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48804508/