这是方法:
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());
TestPageResult是:
protected static class TestPageResult<T> {
private List<T> items;
private long totalCount = -1;
public TestPageResult() {
}
//omitted getters and setters
}
生成的pageResult.getItems()包含LinkedHashMap的List而不是SomeDto的列表。如果我只是在objectMapper.readValue方法中对SomeDto类型进行硬编码,我会得到正确的结果。
有什么问题?
编辑:建议的重复确实解决了我的问题 - 有点。 我用过:
JavaType type = getObjectMapper().getTypeFactory().constructParametricType(TestPageResult.class, clazz);
TestPageResult<T> response = getObjectMapper().readValue(responseJson, type);
问题是没有将没有传递给方法的Class参数。因此,由于传递泛型类型和类相同,因此该方法看起来很丑陋。显然你现在不能传递通用,但这样就需要一个连接并添加SuppressWarnings等等。
答案 0 :(得分:0)
问题是擦除。所有这些<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
你真正想要的是什么。你最好的办法是修补并提出解决它的最干净的代码。泛型允许你表达非常精细的结构,当你序列化一个实际的实例(嵌套对象)时,它就会很好,但是当需要在运行时对类进行内省时,例如对于反序列化(您的用例)或构建模型(例如生成Swagger文档),这就成了问题。