Java泛型与Jackson序列化问题:返回LinkedHashMap而非目标类型
问题描述
定义了泛型API响应类ApiResponse:
@Setter @Getter public final class ApiResponse<T> { private T data; }
通过Jackson解析HTTP响应体生成ApiResponse的Converter类:
class Converter<T> { ApiResponse<T> create(){ // 此步骤前有REST调用并生成httpResponse ApiResponse<T> apiResponse = new ApiResponse(); T data = objectMapper .readValue(httpResponse.body(), new TypeReference<>() {}); apiResponse.setData(data); return apiResponse; } }
使用自定义对象MyObject调用时:
Converter<MyObject> converter = new Converter<>(); ApiResponse<MyObject> apiResponse = converter.create();
发现apiResponse.getData()返回的是LinkedHashMap而非MyObject类型。
MyObject类定义:
@Getter @Builder @NoArgsConstructor @AllArgsConstructor @JsonIgnoreProperties(ignoreUnknown = true) public final class MyObject { @JsonProperty("childs") private ChildObject[] childs; }
参考HTTP响应体:
{ "childs": [ { "freightLineId": "", "shipmentId": "", "shipmentVersionId": "" } ] }
问题原因
Java的泛型类型擦除导致Jackson无法识别T的实际类型。在Converter的create方法中,new TypeReference<>() {}是匿名内部类,但编译后泛型T的具体类型信息会被擦除,Jackson无法知晓要将JSON反序列化为MyObject,只能默认解析成LinkedHashMap。
解决方案
方案1:传入TypeReference参数
修改Converter的create方法,由调用方提供带有实际类型信息的TypeReference:
class Converter<T> { ApiResponse<T> create(TypeReference<T> typeReference){ ApiResponse<T> apiResponse = new ApiResponse(); T data = objectMapper .readValue(httpResponse.body(), typeReference); apiResponse.setData(data); return apiResponse; } }
调用时指定类型:
Converter<MyObject> converter = new Converter<>(); ApiResponse<MyObject> apiResponse = converter.create(new TypeReference<MyObject>() {});
方案2:传入Class参数
如果不需要处理嵌套泛型这类复杂场景,直接传入目标类的Class对象即可:
class Converter<T> { ApiResponse<T> create(Class<T> clazz){ ApiResponse<T> apiResponse = new ApiResponse(); T data = objectMapper .readValue(httpResponse.body(), clazz); apiResponse.setData(data); return apiResponse; } }
调用时传入MyObject.class:
Converter<MyObject> converter = new Converter<>(); ApiResponse<MyObject> apiResponse = converter.create(MyObject.class);
方案3:在Converter初始化时传入类型信息
提前将类型信息注入Converter实例,避免每次调用都传参数:
class Converter<T> { private final TypeReference<T> typeReference; public Converter(TypeReference<T> typeReference) { this.typeReference = typeReference; } ApiResponse<T> create(){ ApiResponse<T> apiResponse = new ApiResponse(); T data = objectMapper .readValue(httpResponse.body(), typeReference); apiResponse.setData(data); return apiResponse; } }
创建Converter时指定类型:
Converter<MyObject> converter = new Converter<>(new TypeReference<MyObject>() {}); ApiResponse<MyObject> apiResponse = converter.create();
内容的提问来源于stack exchange,提问作者Rahul Raj
相关产品推荐
相关产品推荐

