当尝试获取JSON请求并处理它时,我得到以下错误:
org.codehaus.jackson.map。JsonMappingException:没有找到适合类型[简单类型,类com.myweb]的构造函数。:不能从JSON对象实例化(需要添加/启用类型信息吗?)
这是我要发送的JSON:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
在Controller中,我有以下方法签名:
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
AllApplesDO是ApplesDO的包装:
public class AllApplesDO {
private List<ApplesDO> applesDO;
public List<ApplesDO> getApplesDO() {
return applesDO;
}
public void setApplesDO(List<ApplesDO> applesDO) {
this.applesDO = applesDO;
}
}
ApplesDO:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String appl) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
}
我认为Jackson无法将JSON转换为子类的Java对象。请帮忙提供Jackson将JSON转换为Java对象的配置参数。我正在使用Spring Framework。
编辑:包含了导致上述示例类中此问题的主要错误-请查看接受的解决方案答案。
所以,我终于意识到问题是什么了。这不是我所怀疑的Jackson配置问题。
实际上问题在ApplesDO Class:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom) {
//constructor Code
}
}
为该类定义了自定义构造函数,使其成为默认构造函数。引入虚拟构造函数使错误消失:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom) {
//constructor Code
}
//Introducing the dummy constructor
public ApplesDO() {
}
}
发生这种情况的原因如下:
-
内部类应该定义为static
private static class Condition { //jackson specific }
-
这可能是你没有默认的构造函数在你的类(UPDATE:这似乎不是这种情况)
private static class Condition { private Long id; public Condition() { } // Setters and Getters }
-
可能是你的setter没有正确定义或不可见(例如private setter)
我想添加另一个不需要虚拟构造函数的解决方案。因为虚拟构造函数有点混乱,随后令人困惑。我们可以提供一个安全的构造函数,并通过注释构造函数实参,允许jackson确定构造函数形参和字段之间的映射。
所以下面的也可以工作。注意注释中的字符串必须与字段名匹配。
import com.fasterxml.jackson.annotation.JsonProperty;
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
public ApplesDO(@JsonProperty("apple")String apple) {
}
}
当我遇到这个问题时,这是试图使用内部类作为DO的结果。内部类的构造(静默的)需要一个封闭类的实例——这对于Jackson来说是不可用的。
在这种情况下,将内部类移动到它自己的.java文件中可以解决这个问题。
通常,出现此错误是因为我们没有创建默认构造函数。
但在我的情况下:
这个问题的出现仅仅是因为我在父类中使用了对象类。
这浪费了我一整天的时间。
经验法则:为您用作映射类的每个类添加默认构造函数。你错过了这一点,问题出现了!
只需添加默认构造函数,它就可以工作了。
您能测试一下这个结构吗?如果我没记错的话,你可以这样用:
{
"applesRequest": {
"applesDO": [
{
"apple": "Green Apple"
},
{
"apple": "Red Apple"
}
]
}
}
第二,请为每个类添加默认构造函数,这也可能有所帮助。
您必须在我们的模型类中创建虚拟空构造函数。映射json时,它通过setter方法进行设置。
关于上次发布,我在使用Lombok 1.18时遇到了同样的问题。*生成问题。
我的解决方案是添加@NoArgsConstructor(不带参数的构造函数),因为@Data默认包含@RequiredArgsConstructor(带参数的构造函数)。
lombok文档https://projectlombok.org/features/all
这将解决问题:
package example.counter;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Data
@NoArgsConstructor
public class CounterRequest {
@NotNull
private final Integer int1;
@NotNull
private final Integer int2;
}
如果你开始注释构造函数,你必须注释所有字段。
注意,我的Staff.name字段映射到JSON字符串中的"ANOTHER_NAME"。
String jsonInString="{"ANOTHER_NAME":"John","age":"17"}";
ObjectMapper mapper = new ObjectMapper();
Staff obj = mapper.readValue(jsonInString, Staff.class);
// print to screen
public static class Staff {
public String name;
public Integer age;
public Staff() {
}
//@JsonCreator - don't need this
public Staff(@JsonProperty("ANOTHER_NAME") String n,@JsonProperty("age") Integer a) {
name=n;age=a;
}
}
您必须了解Jackson有哪些可用于反序列化的选项。在Java中,编译后的代码中不存在方法参数名。这就是为什么Jackson一般不能使用构造函数来创建一个定义良好的对象。
所以,如果有空构造函数和setter,它使用空的构造函数和setter。如果没有设置器,则使用一些黑魔法(反射)来实现。
如果你想对Jackson使用构造函数,你必须使用@PiersyP在他的回答中提到的注释。您还可以使用构建器模式。如果你遇到了一些例外,祝你好运。Jackson中的错误处理非常糟糕,很难理解错误消息中的乱码。
为所有实体类添加默认构造函数
自定义jackson序列化器/反序列化器失败也可能是问题所在。虽然这不是你的情况,但还是值得一提。
我遇到了同样的异常,情况就是这样。
对于我来说,这曾经是有效的,但是升级库导致这个问题出现。问题是有这样一个类:
package example.counter;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Data
public class CounterRequest {
@NotNull
private final Integer int1;
@NotNull
private final Integer int2;
}
使用lombok: <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
回到
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
修复了这个问题。不知道为什么,但想记录下来以备将来使用