泽西岛:没有为类型[简单类型,类Thing]找到合适的构造函数:无法从JSON对象实例化

2022-09-01 12:59:34

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

@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 中?


答案 1

您需要一个无 arg 构造函数和 setter,或者使用 .最简单的办法就是用 setter 添加 no-arg。杰克逊在反序列化时需要二传手。对于序列化,所需要的只是 getter。@JsonCreator

编辑

若要使其不可变,可以在构造函数上使用。例如@JsonCreator

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

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

查看更多杰克逊注释:@JsonCreator揭秘


答案 2

我不是绝对积极的,但我认为就是这样。

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


推荐