我有一个使用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);
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个其他选项:
您可以将其映射到不同的类型,然后将其转换为有界列表。