提问者:小点点

Jackson InvalidDefitionException:无法构造实例,因为没有找到默认的无参数构造函数


我有一个使用Spring Boot提供REST功能的应用程序。我在将POST响应反序列化为POJO时遇到问题。例外如下:

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [collection type; class uci.BoundedList, contains [simple type, class java.lang.Object]]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `uci.BoundedList` (no Creators, like default construct, exist): no default no-arguments constructor found

BoundedList类型是使用XJC从XML模式生成的API的一部分。我无法控制这个类是如何生成的。事实证明,它是java. util.ArrayList的子类,并且只定义了一个构造函数:

public BoundedList(int minOccurs, int maxOccurs) {
    super();
    this.minOccurs = minOccurs;
    this.maxOccurs = maxOccurs;
}

它没有定义无参数构造函数,这似乎是异常所抱怨的。

由于我不能修改这个类,它是我正在使用的API的一个组成部分,我可以做些什么来解决这个问题?我可以提供某种定制的类/接口来满足杰克逊数据绑定吗?一些其他可能的解决方案?

更新:

我根据下面提供的答案尝试了许多建议。没有一个奏效。我正在研究“混合”方法,我承认我不太明白它应该如何工作。我读过的许多文章写得很简单,但它似乎仍然有点“黑魔法”。

无论如何,以下是我根据所读内容尝试做的片段:

“混入”类:

public abstract class BoundedListMixin {
  @JsonCreator
  public BoundedListMixin(@JsonProperty("minOccurs") int minOccurs,
      @JsonProperty("maxOccurs") int maxOccurs) {}
}

添加到现有配置类的内容:

@Configuration
@EnableAsync
@EnableScheduling
@ComponentScan("<package>")
public class ServiceConfigurer {
  @Bean
  @Primary
  public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper mapper = builder.createXmlMapper(false).build();
    mapper.addMixIn(BoundedList.class, BoundedListMixin.class);
    return mapper;
  }
}

我可以确认配置类中的object tMapper()方法正在通过调试器调用。

这个链接(https://dzone.com/articles/jackson-mixin-to-the-rescue)引入了另一个方面,但是唉,这也不起作用。

更新:

我已将ServiceConfigrer(上图)中的object tMapper()方法替换为以下内容:

  @Bean
  public Jackson2ObjectMapperBuilderCustomizer objectMapperCustomizer() {
    return new Jackson2ObjectMapperBuilderCustomizer() {
      @Override
      public void customize(Jackson2ObjectMapperBuilder builder) {
        builder.mixIn(BoundedList.class, BoundedListMixin.class);
      }
    };
  }

我仍然有同样的问题。这个问题必须与其他一些问题有关。

注:

我还应该澄清,当我调用GET时,这个问题就会显现出来。我有一个简单的RESTendpoint,它只是请求服务返回一个POJO。奇怪的是,如果我从浏览器发送请求,对象会JSON返回并呈现。但是,当它从代码中调用时,我得到了上面的异常。

GET调用:

RequestStatus statusMsg = template.getForObject("http://localhost:8080/rst/missionPlanning/data", RequestStatus.class);

共3个答案

匿名用户

Jackson需要一个没有参数的默认构造函数或构造函数参数上的注释,以找出JSON对象中的哪个字段应该映射到参数。类似于这样:

@JsonCreator
public BoundedList(@JsonProperty("min") int minOccurs, @JsonProperty("max") int maxOccurs) {
   // your code
}

当你不能改变课程时,你可以使用杰克逊混音器

abstract class MixIn {
   MixIn(@JsonProperty("min") int minOccurs, @JsonProperty("max") int maxOccurs) { }
}

并在对象映射器上配置它,如下所示:

objectMapper.addMixInAnnotations(BoundedList.class, MixIn.class);

详见https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInAnnotations。

匿名用户

最简单的方法是将Jackson注释添加到POJO以指导它如何反序列化。这个问题很好地描述了它。

但是,由于您的POJO是自动生成的,您无法修改它,因此还有2个其他选项:

  1. 使用自定义反序列化器手动将JSON负载解析为POJO的实例
  2. 使用混合函数用所需的注释装饰POJO

匿名用户

您可以将其映射到不同的类型,然后将其转换为有界列表。