我一直在谷歌搜索,试图找出如何做到这一点:我有一个 Jersey REST 服务。调用 REST 服务的请求包含一个 JSON 对象。我的问题是,从 Jersey POST 方法实现中,我如何才能访问 HTTP 请求正文中的 JSON?
任何提示、技巧、示例代码的指针将不胜感激。
谢谢...
--史蒂夫
最佳答案
正如已经建议的那样,将 @Consumes
Content-Type 更改为 text/plain
会起作用,但从 REST API 的角度来看,它似乎并不正确。
假设您的客户必须将 JSON 发布到您的 API,但需要将 Content-Type header 指定为 text/plain
。在我看来它并不干净。简单来说,如果您的 API 接受 JSON,则请求 header 应指定 Content-Type: application/json
。
为了接受 JSON 但将其序列化为 String
对象而不是 POJO,您可以实现自定义 MessageBodyReader .这样做同样容易,而且您不必在 API 规范上妥协。
值得阅读 MessageBodyReader 的文档所以你确切地知道它是如何工作的。我就是这样做的:
步骤 1. 实现自定义 MessageBodyReader
@Provider
@Consumes("application/json")
public class CustomJsonReader<T> implements MessageBodyReader<T> {
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations,MediaType mediaType) {
return true;
}
@Override
public T readFrom(Class<T> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException, WebApplicationException {
/* Copy the input stream to String. Do this however you like.
* Here I use Commons IOUtils.
*/
StringWriter writer = new StringWriter();
IOUtils.copy(entityStream, writer, "UTF-8");
String json = writer.toString();
/* if the input stream is expected to be deserialized into a String,
* then just cast it
*/
if (String.class == genericType)
return type.cast(json);
/* Otherwise, deserialize the JSON into a POJO type.
* You can use whatever JSON library you want, here's
* a simply example using GSON.
*/
return new Gson().fromJson(json, genericType);
}
}
上面的基本概念是检查输入流是否期望被转换为String
(由Type genericType
指定)。如果是这样,那么只需将 JSON 转换为指定的 type
(这将是一个 String
)。如果预期类型是某种 POJO,则使用 JSON 库(例如 Jackson 或 GSON)将其反序列化为 POJO。
第二步,绑定(bind)你的MessageBodyReader
这取决于您使用的框架。我发现 Guice 和 Jersey 配合得很好。这是我如何绑定(bind)我的MessageBodyReader在古斯:
在我的JerseyServletModule我像这样绑定(bind)阅读器--
bind(CustomJsonReader.class).in(Scopes.SINGLETON);
上面的 CustomJsonReader
会将 JSON 有效负载反序列化为 POJO,如果您只是想要原始 JSON,还可以将 String
对象反序列化。
这样做的好处是它会接受Content-Type: application/json
。换句话说,您的请求处理程序可以设置为使用 JSON,这似乎是正确的:
@POST
@Path("/stuff")
@Consumes("application/json")
public void doStuff(String json) {
/* do stuff with the json string */
return;
}
关于json - 在 Jersey 服务中使用 JSON 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1662490/