JsonMappingException:找不到类型 [简单类型,类] 的合适构造函数:无法从 JSON 对象实例化
我在尝试获取 JSON 请求并处理它时收到以下错误:
org.codehaus.jackson.map.JsonMappingException:找不到类型[简单类型,类 com.myweb.ApplesDO] 的合适构造函数:无法从 JSON 对象实例化(需要添加/启用类型信息?)
这是我的JSON尝试发送:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
在控制器中,我有以下方法签名:
@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 框架。
编辑:在上面的示例类中包含导致此问题的主要错误 - 请查看已接受的答案以获取解决方案。
I am getting the following error when trying to get a JSON request and process it:
org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class com.myweb.ApplesDO]: can not instantiate from JSON object (need to add/enable type information?)
Here is the JSON I am trying to send:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
In Controller, I have the following method signature:
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
AllApplesDO is a wrapper of 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
}
}
I think that Jackson is unable to convert JSON into Java objects for subclasses. Please help with the configuration parameters for Jackson to convert JSON into Java Objects. I am using Spring Framework.
EDIT: Included the major bug that is causing this problem in the above sample class - Please look accepted answer for solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
所以,最后我意识到问题是什么。这不是我怀疑的杰克逊配置问题。
实际上问题出在 ApplesDO 类中:
为该类定义了一个自定义构造函数,使其成为默认构造函数。引入虚拟构造函数使错误消失:
So, finally I realized what the problem is. It is not a Jackson configuration issue as I doubted.
Actually the problem was in ApplesDO Class:
There was a custom constructor defined for the class making it the default constructor. Introducing a dummy constructor has made the error to go away:
发生这种情况的原因如下:
您的内部类应定义为静态
这可能是你的类中没有默认构造函数(更新:这似乎事实并非如此)
可能是您的 Setter 定义不正确或不可见(例如私有设置器)
This happens for these reasons:
your inner class should be defined as static
It might be that you got no default constructor in your class (UPDATE: This seems not to be the case)
It could be your Setters are not defined properly or are not visible (e.g. private setter)
我想为此添加另一个不需要虚拟构造函数的解决方案。由于虚拟构造函数有点混乱,因此令人困惑。我们可以提供一个安全的构造函数,并通过注释构造函数参数,我们允许杰克逊确定构造函数参数和字段之间的映射。
所以下面的方法也可以工作。请注意,注释内的字符串必须与字段名称匹配。
I would like to add another solution to this that does not require a dummy constructor. Since dummy constructors are a bit messy and subsequently confusing. We can provide a safe constructor and by annotating the constructor arguments we allow jackson to determine the mapping between constructor parameter and field.
so the following will also work. Note the string inside the annotation must match the field name.
当我遇到这个问题时,这是由于尝试使用内部类作为 DO 的结果。内部类的构造(默默地)需要一个封闭类的实例——杰克逊无法使用该实例。
在这种情况下,将内部类移至其自己的 .java 文件可以解决该问题。
When I ran into this problem, it was a result of trying to use an inner class to serve as the DO. Construction of the inner class (silently) required an instance of the enclosing class -- which wasn't available to Jackson.
In this case, moving the inner class to its own .java file fixed the problem.
一般来说,出现此错误是因为我们没有创建默认构造函数。
但就我而言:
这个问题的出现只是因为我在父类中使用了对象类。
这浪费了我一整天的时间。
Generally, this error comes because we don’t make default constructor.
But in my case:
The issue was coming only due to I have made used object class inside parent class.
This has wasted my whole day.
经验法则:为用作映射类的每个类添加默认构造函数。您错过了这一点,问题就出现了!
只需添加默认构造函数就可以了。
Thumb Rule: Add a default constructor for each class you used as a mapping class. You missed this and issue arise!
Simply add default constructor and it should work.
你能测试一下这个结构吗?如果我没记错的话,你可以这样使用它:
其次,请为每个类添加默认构造函数,这也可能会有所帮助。
Can you please test this structure. If I remember correct you can use it this way:
Second, please add default constructor to each class it also might help.
你必须在我们的模型类中创建虚拟的空构造函数。因此,在映射 json 时,它是通过 setter 方法设置的。
You have to create dummy empty constructor in our model class.So while mapping json, it set by setter method.
关于上一篇文章,我遇到了同样的问题,即使用 Lombok 1.18.* 产生了该问题。
我的解决方案是添加@NoArgsConstructor(不带参数的构造函数),因为@Data默认包含@RequiredArgsConstructor(带参数的构造函数)。
龙目岛文档
https://projectlombok.org/features/all
这可以解决问题:
Regarding the last publication I had the same problem where using Lombok 1.18.* generated the problem.
My solution was to add @NoArgsConstructor (constructor without parameters), since @Data includes by default @RequiredArgsConstructor (Constructor with parameters).
lombok Documentation
https://projectlombok.org/features/all
That would solve the problem:
如果开始注释构造函数,则必须注释所有字段。
请注意,我的 Staff.name 字段映射到 JSON 字符串中的“ANOTHER_NAME”。
If you start annotating constructor, you must annotate all fields.
Notice, my Staff.name field is mapped to "ANOTHER_NAME" in JSON string.
您必须了解 Jackson 有哪些可用于反序列化的选项。在 Java 中,方法参数名称不存在于编译后的代码中。这就是为什么 Jackson 通常不能使用构造函数来创建一个定义明确的对象(所有内容都已设置)。
因此,如果有一个空构造函数并且还有 setter,那么它会使用空构造函数和 setter。如果没有设定器,则使用一些黑魔法(反射)来做到这一点。
如果您想在 Jackson 中使用构造函数,则必须使用 @PiersyP 在其答案中提到的注释。您还可以使用构建器模式。如果您遇到一些异常,祝您好运。 Jackson 中的错误处理很糟糕,很难理解错误消息中的乱码。
You must realize what options Jackson has available for deserialization. In Java, method argument names are not present in the compiled code. That's why Jackson can't generally use constructors to create a well-defined object with everything already set.
So, if there is an empty constructor and there are also setters, it uses the empty constructor and setters. If there are no setters, some dark magic (reflections) is used to do it.
If you want to use a constructor with Jackson, you must use the annotations as mentioned by @PiersyP in his answer. You can also use a builder pattern. If you encounter some exceptions, good luck. Error handling in Jackson sucks big time, it's hard to understand that gibberish in error messages.
为所有实体类添加默认构造函数
Add default constructors to all the entity classes
自定义杰克逊序列化器/反序列化器失败也可能是问题。虽然这不是你的情况,但值得一提。
我遇到了同样的例外,情况就是如此。
Failing custom jackson Serializers/Deserializers could also be the problem. Though it's not your case, it's worth mentioning.
I faced the same exception and that was the case.
对我来说,这曾经有效,但升级库导致出现此问题。问题是有这样的课程:
使用lombok:
回退到
修复问题。不知道为什么,但想记录下来以供将来使用。
For me, this used to work, but upgrading libraries caused this issue to appear. Problem was having a class like this:
Using lombok:
Falling back to
Fixed the issue. Not sure why, but wanted to document it for future.