Luc*_*ari 422 java spring json annotations jackson
我在尝试获取JSON请求并处理它时收到以下错误:
org.codehaus.jackson.map.JsonMappingException:找不到类型[simple type,class com.myweb.ApplesDO]的合适构造函数:无法从JSON对象实例化(需要添加/启用类型信息?)
这是我要发送的JSON:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
Run Code Online (Sandbox Code Playgroud)
在Controller中,我有以下方法签名:
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
Run Code Online (Sandbox Code Playgroud)
AllApplesDO是ApplesDO的包装器:
public class AllApplesDO {
private List<ApplesDO> applesDO;
public List<ApplesDO> getApplesDO() {
return applesDO;
}
public void setApplesDO(List<ApplesDO> applesDO) {
this.applesDO = applesDO;
}
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
我认为Jackson无法将JSON转换为子类的Java对象.请帮助Jackson将JSON转换为Java Objects的配置参数.我正在使用Spring Framework.
编辑:包括在上面的示例类中导致此问题的主要错误 - 请查看接受的解决方案的答案.
Luc*_*ari 551
所以,最后我意识到问题所在.我怀疑这不是杰克逊的配置问题.
实际上问题出在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
}
}
Run Code Online (Sandbox Code Playgroud)
为类定义了一个自定义构造函数,使其成为默认构造函数.引入虚拟构造函数已使错误消失:
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() {
}
}
Run Code Online (Sandbox Code Playgroud)
aze*_*ati 371
出现这种情况的原因如下:
你的内部类应该定义为静态
private static class Condition { //jackson specific
}
Run Code Online (Sandbox Code Playgroud)可能是你的类中没有默认构造函数(更新:似乎不是这种情况)
private static class Condition {
private Long id;
public Condition() {
}
// Setters and Getters
}
Run Code Online (Sandbox Code Playgroud)可能是您的Setter未正确定义或不可见(例如私人制定者)
Pie*_*syP 58
我想为此添加另一个不需要虚拟构造函数的解决方案.因为虚拟构造函数有点混乱并且随后令人困惑.我们可以提供一个安全的构造函数,并通过注释构造函数参数,我们允许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) {
}
}
Run Code Online (Sandbox Code Playgroud)
jma*_*rks 31
当我遇到这个问题时,它是尝试使用内部类作为DO的结果.构建内部类(默默地)需要一个封闭类的实例 - 杰克逊无法获得.
在这种情况下,将内部类移动到其自己的.java文件可以解决问题.
alo*_*lok 17
一般来说,这错误出现,因为我们不作默认构造函数,但在我的情况的问题是未来不仅是因为我做了父类中使用的对象类.这浪费了我一整天.
你能测试一下这个结构吗?如果我记得没错,你可以这样使用它:
{
"applesRequest": {
"applesDO": [
{
"apple": "Green Apple"
},
{
"apple": "Red Apple"
}
]
}
}
Run Code Online (Sandbox Code Playgroud)
其次,请为每个类添加默认构造函数,它也可能有所帮助.
小智 6
关于上次发布,我遇到了同样的问题,使用 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;
}
Run Code Online (Sandbox Code Playgroud)
您必须了解 Jackson 有哪些可用于反序列化的选项。在 Java 中,方法参数名称不存在于编译代码中。这就是为什么杰克逊通常不能使用构造函数来创建一个已经设置好一切的定义良好的对象。
所以,如果有一个空的构造函数并且也有 setter,它会使用空的构造函数和 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;
}
}
Run Code Online (Sandbox Code Playgroud)