JsonMappingException:没有为类型[简单类型,类]找到合适的构造函数:不能从JSON对象实例化

我得到以下错误时,试图获得一个JSON请求和处理它:

jsonmappingexception:没有为类型[简单类型,类com.myweb.]找到合适的构造函数。ApplesDO]:不能从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框架。

编辑:在上面的示例类中包含了导致此问题的主要错误-请查看解决方案的接受答案。

472226 次浏览

你能测试一下这个结构吗?如果我没记错的话,你可以这样用:

{
"applesRequest": {
"applesDO": [
{
"apple": "Green Apple"
},
{
"apple": "Red Apple"
}
]
}
}

其次,请为每个类添加默认构造函数,这也可能有所帮助。

所以,我终于意识到问题所在。这不是一个杰克逊配置问题,我怀疑。

实际上问题在ApplesDO类中:

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() {
}


}

出现这种情况的原因如下:

  1. 你的内部类应该定义为静态

    private static class Condition {  //jackson specific
    }
    
  2. It might be that you got no default constructor in your class (UPDATE: This seems not to be the case)

    private static class Condition {
    private Long id;
    
    
    public Condition() {
    }
    
    
    // Setters and Getters
    }
    
  3. It could be your Setters are not defined properly or are not visible (e.g. 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) {
}


}

经验法则:为每个用作映射类的类添加默认构造函数。你错过了这个问题出现了!< br > 简单地添加默认构造函数,它应该工作

当我遇到这个问题时,这是试图使用内部类作为DO的结果。内部类的构造(静默地)需要一个外围类的实例——Jackson无法使用这个实例。

在这种情况下,将内部类移动到它自己的.java文件中解决了这个问题。

自定义jackson序列化器/反序列化器失败也可能是问题所在。虽然不是你的案子,但还是值得一提。

我也遇到过同样的例外情况。

您必须了解Jackson有哪些反序列化选项。在Java中,方法参数名不会出现在编译后的代码中。这就是为什么Jackson通常不能使用构造函数来创建一个定义良好的对象。

如果有一个空构造函数,同时也有setter,它使用空构造函数和setter。如果没有设置,则使用一些黑魔法(反射)来做到这一点。

如果希望在Jackson中使用构造函数,则必须使用@PiersyP在他的回答中提到的注释。您还可以使用构建器模式。如果遇到一些例外,祝你好运。Jackson中的错误处理非常糟糕,很难理解错误消息中的胡言乱语。

如果开始注释构造函数,则必须注释所有字段。

注意,我的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;
}
}

您必须在模型类中创建虚拟空构造函数。映射json时,它由setter方法设置。

对我来说,这曾经是可行的,但升级库会导致这个问题出现。问题是有这样一门课:

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>

修正了这个问题。不知道为什么,但想记录下来以备将来之用。

通常,这个错误是因为我们不要创建默认构造函数
但在我的例子中:
问题的到来只是由于我已经父类中使用的对象类
这浪费了我一整天。

关于上一个版本,我在使用Lombok 1.18时遇到了同样的问题。*产生了问题。

我的解决方案是添加@NoArgsConstructor(不带参数的构造函数),因为@Data默认包含@RequiredArgsConstructor(带参数的构造函数)。

< p > lombok文档 https://projectlombok.org/features/all < / p >

这将解决问题:

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;
}

向所有实体类添加默认构造函数