克服“不能构造interfaceclass的示例”而不提示父对象

u1ehiz5o  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(327)

我的控制器中有以下方法:

  1. @RequestMapping(method = RequestMethod.POST)
  2. InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
  3. // Do something
  4. }

我得到的错误是非常直接和不言自明的:

  1. 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 .
我试过:

  1. @JsonRootName("InterfaceClass")
  2. public class ClassImpl implements InterfaceClass {
  3. }

完全没有。我不能用 @JsonTypeInfo 作为父接口类 InterfaceClass 不应该意识到 ClassImpl 它们在不同的模块中。我也尝试过:
实施 InterfaceClass 带摘要 AbstractClass 然后说:

  1. @JsonDeserialize(as = AbstractClass.class)

在…之上 InterfaceClass . 然后延伸 AbstractClassClassImpl . 错误只会变成:

  1. Can not construct instance of InterfaceClass: abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information.

进一步尝试:

  1. public class ControllerClass<E extends InterfaceClass> {
  2. @RequestMapping(method = RequestMethod.POST)
  3. InterfaceClass insert(@RequestBody E interfaceClass) {
  4. InterfaceClass object = (InterfaceClass) interfaceClass;
  5. }
  6. }

结果是:

  1. java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to InterfaceClass

一如预期。
我真的很期待springboot处理组件发现,因为只有一个具体的实现 InterfaceClass 或者 AbstractClass ,即 ClassImpl 在我的课堂上。也许我做错了什么?我怎样才能克服这一点,而不明确暗示 InterfaceClass 在何处实施(例如:否 @JsonDeserialize 等等)?

8dtrkrch

8dtrkrch1#

解决方案1-动态注册子类型

可以动态定义子类型。
1.在接口上,定义要用作标识符的json字段(@type):

  1. @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
  2. include = JsonTypeInfo.As.PROPERTY, property = "@type")
  3. public interface InterfaceClass {
  4. }

2.将“@type”字段添加到json负载中

  1. {
  2. ...
  3. "@type": "someName"
  4. }

2.动态注册接口的子类型:

  1. @Bean
  2. public Jackson2ObjectMapperBuilder objectMapperBuilder() {
  3. Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() {
  4. public void configure(ObjectMapper objectMapper) {
  5. objectMapper.registerSubtypes(ClassImpl.class);
  6. super.configure(objectMapper);
  7. };
  8. };
  9. return builder;
  10. }

4.在具体类中指定“@type”名称(可选):

  1. //Optional, otherwise uses the Simple class name (ie: 'ClassImpl')
  2. @JsonTypeName("someName")
  3. public class ClassImpl implements InterfaceClass {
  4. }

5.use现在可以使用带有@requestbody的接口:

  1. @RequestMapping(method = RequestMethod.POST)
  2. InterfaceClass insert(@RequestBody InterfaceClass interfaceClass) {
  3. }

解决方案2-动态注册自定义反序列化程序

如果添加 @type 字段是不可能的(或者不需要),您还可以为接口定义一个自定义反序列化程序,这实际上会创建一个 ClassImpl :
1.定义自定义反序列化程序:

  1. class ClassImplJsonDeserializer extends JsonDeserializer<ClassImpl> {
  2. @Override
  3. public ClassImpl deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
  4. return jp.readValuesAs(ClassImpl.class).next();
  5. }
  6. }

2.动态设置自定义反序列化程序:

  1. @Bean
  2. public Jackson2ObjectMapperBuilder objectMapperBuilder() {
  3. Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
  4. builder.deserializerByType(InterfaceClass.class, new ClassImplJsonDeserializer());
  5. return builder;
  6. }

3.从接口中删除@jsontypeinfo:

  1. public interface InterfaceClass {
  2. }
展开查看全部

相关问题