【问题标题】:Jersey: No suitable constructor found for type [simple type, class Thing]: can not instantiate from JSON objectJersey:没有找到适合类型 [simple type, class Thing] 的构造函数:无法从 JSON 对象实例化
【发布时间】:2015-09-14 15:46:53
【问题描述】:

我有一个资源,其方法如下:

@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/add")
public Response putThing(Thing thing) {
    try {
        //Do something with Thing object
        return Response.status(HttpStatus.SC_OK).build();
    } catch (Exception e) {
        log.error("Request failed", e);
        return Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).build();
    }
}

事情:

public class Thing {
    private final String symbol;
    private final String name;

    public Stock(String symbol, String name) {
        this.symbol = symbol;
        this.name = name;
    }

    public String getSymbol() {
        return this.symbol;
    }

    public String getName() {
        return this.name;
    }
}

当我发出 PUT 请求时:

PUT /rest/add HTTP/1.1
Host: localhost:8135
Content-Type: application/json
Cache-Control: no-cache

{"symbol":"some symbol","name":"some name"}

我收到以下回复:

没有为类型 [简单类型,类 Thing] 找到合适的构造函数:可以 不从 JSON 对象实例化(缺少默认构造函数或 创建者,或者可能需要添加/启用类型信息?)

为什么 Jersey/Jackson 没有将我的 JSON 对象反序列化到我的 POJO 中?

【问题讨论】:

标签: java jersey jackson jersey-2.0


【解决方案1】:

你需要一个无参数的构造函数和设置器,或者使用@JsonCreator。最简单的事情就是在 setter 中添加无参数。 Jackson 在反序列化时需要设置器。对于序列化,只需要 getter。

编辑

为了让它不可变,你可以在构造函数上使用@JsonCreator。例如

@JsonCreator
public Thing(@JsonProperty("symbol") String symbol, 
             @JsonProperty("name") String name) {

    this.symbol = symbol;
    this.name = name;
}

查看更多Jackson Annotations: @JsonCreator demystified

【讨论】:

  • 绝对是为了不变性,是的。或者,我相信 ObjectMapper 上的可见性可以设置为 ANY,它将处理私有字段。
【解决方案2】:

我不是绝对肯定,但我认为就是这样。

Jackson 想要的工作方式是这样的:它使用默认(无参数)构造函数创建对象。然后它使用 setter 设置每个实例变量。这可能看起来很长,但它确实是唯一的方法,因为杰克逊不能真正聪明到弄清楚传递构造函数参数的顺序。所以你的代码有两个主要问题(嗯,三个,但是我将假设您的课程在您大部分清理以发布之前称为 Stock ;-) )。
1. 你需要一个无参数的构造函数。据我所知,java 提供了一个默认构造函数,如果你不写的话,但是一旦你创建了任何构造函数,默认的无参数构造函数就会消失。
2. 您需要为您的实例变量设置设置器(将它们公开还不够好,它们必须有实际的设置器)。哦,看起来你的实例变量是最终的,那是行不通的。我最喜欢的管理所有复制/粘贴设置器的方法是使用一个名为 lombok 的库。无论如何,现在你只需要那些二传手。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-29
    • 2016-09-28
    • 2012-10-06
    • 2020-09-05
    • 2015-04-19
    • 2019-03-28
    • 1970-01-01
    相关资源
    最近更新 更多