Java 克服;无法构造InterfaceClass的实例“;没有暗示父母
我的控制器中有此方法:Java 克服;无法构造InterfaceClass的实例“;没有暗示父母,java,spring,spring-boot,spring-annotations,Java,Spring,Spring Boot,Spring Annotations,我的控制器中有此方法: @RequestMapping(method = RequestMethod.POST) InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) { // Do something } 我得到的错误非常直截了当且不言自明: Can not construct instance of InterfaceClass: abstract types either need to be map
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
// Do something
}
我得到的错误非常直截了当且不言自明:
Can not construct instance of InterfaceClass: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information.
基本上,我需要告诉Spring我有一个InterfaceClass
,ClassImpl
的具体实现
我试过:
@JsonRootName("InterfaceClass")
public class ClassImpl implements InterfaceClass {
}
毫无疑问。我不能使用@JsonTypeInfo
,因为父接口类InterfaceClass
不应该知道ClassImpl
,它们在不同的模块中。我也尝试过:
使用abstractAbstractClass
实现InterfaceClass
,并放置:
@JsonDeserialize(as = AbstractClass.class)
在接口类的顶部
。然后使用ClassImpl
扩展AbstractClass
。错误只会变成:
Can not construct instance of InterfaceClass: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information.
进一步审判:
public class ControllerClass<E extends InterfaceClass> {
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody E interfaceClass) {
InterfaceClass object = (InterfaceClass) interfaceClass;
}
}
正如所料
我真的很期待Spring Boot处理组件发现,因为InterfaceClass
或AbstractClass
只有一个具体的实现,那就是我的类路径中的ClassImpl
。也许我做错了什么?我如何克服这一问题,而不显式地暗示接口类
其实现的位置(例如,no@JsonDeserialize
等)?解决方案1-动态注册子类型
可以动态定义子类型
1。在接口上,定义一个JSON字段(@type)用作标识符:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
2。将“@type”字段添加到JSON有效负载中
{
...
"@type": "someName"
}
2。动态注册接口的子类型:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
4。在具体类上指定“@type”名称(可选):
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
5。Use现在可以使用@RequestBody:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
解决方案2-动态注册自定义反序列化程序 如果无法(或不需要)添加
@type
字段,您还可以为接口定义自定义反序列化程序,这实际上会创建ClassImpl
:
1。定义自定义反序列化程序:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
3。从接口中删除@JsonTypeInfo:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
解决方案1-动态注册子类型
可以动态定义子类型
1。在接口上,定义一个JSON字段(@type)用作标识符:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
2。将“@type”字段添加到JSON有效负载中
{
...
"@type": "someName"
}
2。动态注册接口的子类型:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
4。在具体类上指定“@type”名称(可选):
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
5。Use现在可以使用@RequestBody:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
解决方案2-动态注册自定义反序列化程序 如果无法(或不需要)添加
@type
字段,您还可以为接口定义自定义反序列化程序,这实际上会创建ClassImpl
:
1。定义自定义反序列化程序:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}
3。从接口中删除@JsonTypeInfo:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "@type")
public interface InterfaceClass {
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
public void configure(ObjectMapper objectMapper) {
objectMapper.registerSubtypes(ClassImpl.class);
super.configure(objectMapper);
};
};
return builder;
}
//Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
@JsonTypeName("someName")
public class ClassImpl implements InterfaceClass {
}
@RequestMapping(method = RequestMethod.POST)
InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
}
class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
@Override
public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return jp.readValuesAs(ClassImpl.class).next();
}
}
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
return builder;
}
public interface InterfaceClass {
}