在使用 JAX-RS(Jersey 3.1.1、Jackson 2.14.2)的 Java REST 服务中,我有一个不可变的数据对象,例如:
public class MyDataObj {
private int a;
public static MyDataObj valueOf(String jsonStr) {
return new MyDataObj(new ObjectMapper().readTree(jsonStr).get("a").asInt());
}
public MyDataObj(int a) { this.a = a; }
public int getA() { return a; }
}
我想从请求的 JSON 正文中读取它。为了简洁起见,上面的示例跳过了错误检查等。这是尝试读取请求正文的服务方法:
@POST
@Path("/myService")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response myService(MyDataObj serviceBody) {
String msg = doSomethingMeaningfulWith(serviceBody.getA());
return Response.ok().entity("{ \"result\": \"" + msg + "\" }");
}
使用内容类型“application/json”和正文
{ "a": 42 }
调用服务失败,并出现 HTTP 415“不支持的媒体类型”错误。例外的是
org.eclipse.persistence.exceptions.JAXBException Exception Description: The class MyDataObj requires a zero argument constructor or a specified factory method. Note that non-static inner classes do not have zero argument constructors and are not supported.
如果我使用
@HeaderParam
(并在请求标头中发送数据)或 @QueryParam
(在 GET 请求中发送数据)注释“serviceBody”参数,上面的代码确实会成功,因为 JAX-RS 指定了您可以使用静态“valueOf”方法自行从 JSON 构造对象,该方法采用单个“String”作为参数,而不是使用默认构造函数和 setter。
但是上面的例子中“valueOf”静态方法不会被调用。
现在的问题是:如何在某个地方注册一个“工厂方法”来构造该对象?或者有什么替代方法吗?
选项1 最简单的方法是使用
@JsonCreator
注释并提供构造函数:
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public UserData(@JsonProperty("a") int a) {
this.a = a
}