2009-11-02 72 views
32

我一直在谷歌搜索我的屁股试图找出如何做到这一点:我有一个泽西岛REST服务。调用REST服务的请求包含一个JSON对象。我的问题是,从Jersey POST方法实现中,我如何访问HTTP请求正文中的JSON?在Jersey服务中使用JSON对象

任何提示,技巧,示例代码指针将不胜感激。

谢谢...

--Steve

+0

现在所面临的问题similiar。有没有解决方案可以使用对JSONObject的低级访问? – Jugi 2017-05-20 11:45:29

回答

10

我不知道你将如何获得在JSON字符串本身,但是你可以在它包含如下的数据肯定会获得:

定义一个JAXB注释的Java类(C),它具有与在请求上传递的JSON对象相同的结构。

例如一个JSON消息:

​​

使用类似:

@XmlAccessorType(XmlAccessType.FIELD) 
public class C 
{ 
    public String A; 
    public String B; 
} 

然后,你可以在你的资源类定义与C型的参数的方法,当新泽西调用你的方法,JAXB的对象将根据POST的JSON对象创建。

@Path("/resource") 
public class MyResource 
{ 
    @POST 
    public put(C c) 
    { 
    doSomething(c.A); 
    doSomethingElse(c.B); 
    } 
} 
+2

不幸的是,JSON字符串基本上被用作字典而不是真正的POJO。我宁愿不必为JSON对象创建一个新的POJO。 – Steve 2009-11-02 17:51:44

+1

有你看着用化MessageBodyReader(http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/ext/MessageBodyReader.html)。没有尝试过自己,但你也许可以在这一水平获得和JSON流转换为地图等 – Andy 2009-11-02 17:57:07

+4

其实事实证明,它的很多比我想象的简单。我可以将HTTP请求的主体作为字符串参数获取,然后使用任何JSON库(当前使用Google GSON)将请求数据转换为本地对象。 – Steve 2009-11-25 21:11:17

0

使用JSON作为值提交/ POST表单/ HTTP.POST。

@QueryParam jsonString

公共desolveJson(jsonString)

+1

我想过这样做。这只是我不想要的方式。有几个工具包将完整的JSON放入HTTP请求的实际主体中,如果可能的话,我想遵循该模式。 – Steve 2009-11-02 21:12:54

6

这使您可以访问原始帖子。

@POST 
@Path("/") 
@Consumes("text/plain") 
@Produces(MediaType.APPLICATION_JSON) 
public String processRequset(String pData) { 
    // do some stuff, 
    return someJson; 
} 
+1

这是一种从我的客户端传递JSON的流畅而简单的方法,并且不需要服务器/客户端知道我传递的对象。我只是使用GSON将其序列化并附加到帖子中。工作很棒!谢谢。 – bh5k 2012-10-11 17:17:53

14

正如已经建议,改变@Consumes的Content-Type到text/plain将工作,但它似乎从一个角度REST API点不正确。

想象一下,您的客户必须将JSON发布到您的API,但需要将Content-Type标头指定为text/plain。我认为这并不干净。简而言之,如果您的API接受JSON,那么请求标头应指定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。

步骤2.绑定您的MessageBodyReader

这取决于你所使用的架构。我发现吉斯和泽西一起工作得很好。以下是我在吉斯绑定我MessageBodyReader

在我JerseyServletModule我绑定读者像这样 -

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; 
}
11

新泽西支持使用抛弃型的JSONObject和JSONArray所解析的JSONObject低级别的访问。

<dependency> 
    <groupId>org.codehaus.jettison</groupId> 
    <artifactId>jettison</artifactId> 
    <version>1.3.8</version> 
</dependency> 

例如:

{ 
    "A": "a value", 
    "B": "another value" 
} 


@POST 
@Path("/") 
@Consumes(MediaType.APPLICATION_JSON) 
public void doStuff(JSONObject json) { 
    /* extract data values using DOM-like API */ 
    String a = json.optString("A"); 
    Strong b = json.optString("B"); 
    return; 
} 

更多的例子参见Jersey documentation

+4

这不适合我。我得到... '无法识别的字段“A”(类org.json.JSONObject),未标记为可忽略的# ...并且如果我添加以下内容... 'mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false );' ......那么对象来通过空'{}' – crowmagnumb 2014-10-23 22:14:26

+0

,这是不行的。我得到415错误。有没有解决方案,以及为低级别json访问添加什么依赖关系? – Jugi 2017-05-20 12:44:06

相关问题