标题
Jackson无法在Java泛型基类中对对象进行格式化。
问题描述
我想将JSON反序列化为Java泛型基类中的对象,但出现了异常:
ClassCastException: class BaseResult cannot be cast to class MyResult (BaseResult and MyResult are in unnamed module of loader 'app')
字符串
例外情况如下:
public abstract class BaseAction<IT extends BaseInput, RT extends BaseResult> {
public RT execute(final IT inObj) throws Exception {
//...
TypeReference<RT> typeRef = new TypeReference<RT>() {};
return JacksonFunctions.jacksonObjectMapper.readValue(jsonString, typeRef); //ClassCastException!!
}
型
下面是类的定义。
BaseInput.java
public abstract class BaseInput {
}
型
BaseResult.java
@Data
@NoArgsConstructor
public class BaseResult {
@JsonProperty("ErrorCode")
private int errorCode = 0;
@JsonProperty("ErrorMessage")
private String errorMessage = "";
}
型
BaseAction.java
public abstract class BaseAction<IT extends BaseInput, RT extends BaseResult> {
public RT execute(final IT inObj) throws Exception {
//...
TypeReference<RT> typeRef = new TypeReference<RT>() {};
return JacksonFunctions.jacksonObjectMapper.readValue(jsonString, typeRef); //ClassCastException!!
}
}
型
concreate类是:
MyInput.java
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class MyInput extends BaseInput {
private String title;
}
型
MyResult.java
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class MyResult extends BaseResult {
@JsonProperty("Title")
private String title;
@JsonProperty("Description")
private String description;
}
型
MyAction.java
public class MyAction extends BaseAction<MyInput, MyResult> {
}
型
该程序是这样运行的:
MyInput inObj = new MyInput();
inObj.setTitle("Galaxy");
MyAction act = new MyAction();
MyResult resObj = act.execute(inObj); //exception here!
型
我的问题是,MyResult(作为RT)被传递给泛型基类MyAction,它应该可以在BaseAction类中使用(MyResult作为RT)。但是为什么Jackson不能将RT作为MyResult来反序列化JSON字符串,而是作为BaseResult(因此出现了ClassCastException)?!
Jackson工作正常,如下所示,如果我使用MyResult类创建TypeReference:
TypeReference<MyResult> typeRef = new TypeReference<MyResult>() {};
return JacksonFunctions.jacksonObjectMapper.readValue(jsonString, typeRef);
型
作为一种变通方法,我可以把上面的代码带到MyAction,它会工作得很好。
但是由于BaseAction已经有RT(作为MyResult),我不知道为什么它不工作。
1条答案
按热度按时间8dtrkrch1#
我觉得这是由于在编译时发生的类型擦除。
BaseAction
类TypeReference<RT> typeRef = new TypeReference<RT>() {}
中的这一行将只有“BaseResult
的子类”的“内存”,而不是哪个特定的子类。由于每个子类可能有不同的结构,因此您不能安全地将父类转换为它。因此,您可以:
Deserializer
到BaseResult
,它将处理不同的实现,或者BaseResult
中提供一个抽象方法来获取实现的类型。这可以传递给readValue(..)
而不是TypeReference<..>
,如下所示(未编译或测试,仅用于指示想法):个字符