泽西岛,如何发布 JSON 对象列表?

Posted

技术标签:

【中文标题】泽西岛,如何发布 JSON 对象列表?【英文标题】:Jersey, how to POST a list of JSON objects? 【发布时间】:2013-03-13 16:33:00 【问题描述】:

我正在使用 Jersey 1.11 在 Java 中构建一个 RESTful Web 服务,并且在实现使用 JSON 化实体列表的方法时遇到问题。单实例方法工作正常。

我得到的错误是:

Status 400 - Bad Request. The request sent by the client was syntactically incorrect.

我的方法签名如下所示:

@POST
@Path("/some-path/someParam")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String createBatch(List<MyEntity> myEnts, @PathParam("someParam") String someParam)

   ... 

我在请求中发送的 JSON 是 MyEntity JSON 对象的数组:

["field1" : value1, "field2" : value2, "field1" : value3, "field2" : value4, ...]

之前有人问过类似的问题,一个直接的建议是将使用的媒体类型更改为文本并反序列化 JSON manually,但我更喜欢更简洁的解决方案。

我发送的 JSON 在这种情况下是否有效,还是我需要*** 即包装实体?这似乎也有点不自然。

谢谢,

/大卫

【问题讨论】:

我在以下链接上发布了相同的答案....***.com/questions/13242414/… 【参考方案1】:

我认为 PathParam 以及应该由 Jersey(JAX-RS) 解组的 Param 是不可能的。 请尝试删除 PathParam 参数。

如果你需要第二个参数,那么创建一个像这样的新类

@XmlRootElement(name = "example")
public class Example 
  @XmlElement(name = "param")
  private String param;
  @XmlElement(name = "entities")
  private List<MyEntity> entities;

并修改您的方法:

@POST
@Path("/some-path")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public String createBatch(Example example)

   ... 

您的 JSON 应该如下所示:


 "param":"someParam",
 "entities":[
   "field1" : value1, "field2" : value2, "field1" : value3, "field2" : value4, ...]

【讨论】:

我在处理对象列表时遇到了同样的问题。我正在使用 axios post 从客户端发送对象列表并使用 Jax RS 接收它,但我有 500 个内部服务器错误。在您的回答中,您说 JSON 应该是这样的,但如果 JSON 只是对象列表 ["field1" : value1, "field2" : value2, "field1" : value3, "field2" : value4, ...] 我认为你需要一个像entities 这样的根节点,你的日志中打印了什么异常?因为你说你有一个 500 错误。 我创建了一个像entities 这样的根节点,我的列表看起来像这样[entities:[ "field1" : value1, "field2" : value2, "field1" : value3, "field2" : value4, ...] 服务器端没有异常,当我尝试调试它时甚至没有触发 POST 方法 在这里我在阅读您的帖子之前问了这个问题link【参考方案2】:

好的,所以最后我使用一个简单的包装类解决了这个问题,以便生成 items : [ &lt;myEnityInstanceJson1&gt; , &lt;myEnityInstanceJson2&gt; , ... ]。我想有一种方法可以拥有一个通用的wrapper,但现在就可以了:

@XmlRootElement
public class MyEntityWrapper implements Serializable 

    private static final long serialVersionUID = 1L;

    private List<MyEntity> items;

    public MyEntityWrapper() 
        this.items = new ArrayList<MyEntity>();
    

    public MyEntityWrapper(List<MyEntity> items) 
        this.items = items;
    

    public List<MyEntity> getItems() 
        return items;
    

    public void setItems(List<MyEntity> items) 
        this.items = items;
    

【讨论】:

【参考方案3】:

问题是泛型列表类型,由于类型擦除,它在运行时不可用,所以 Jersey 不知道要解组哪种 POJO。

我认为在这种情况下,最简单的解决方案(我知道至少在您的MessageBodyReader 中使用 Jackson 时有效)是只使用普通 Java 数组而不是 List,因此方法签名变为:

public String createBatch(@PathParam("someParam") String someParam, MyEntity[] myEnts)

是的,将@PathParam 和一个消费/未编组的主体参数结合起来应该没问题。

【讨论】:

【参考方案4】:

这是数组的有效 JSON:

"elements": [
        "field1" : value1, "field2" : value2, 
        "field1" : value3, "field2" : value4,
        ...]
;

(参见here 示例)

您不需要发送文本,您可以将其作为 JSON 发送。此外,您的MyEntity 上应该有@XmlRootElement(参见here,5.2 节的示例)。

您的参数中不需要PathParam,如果您在方法签名中留下@Path("/some-path/someParam"),则在发布请求时someParam 可用。

【讨论】:

【参考方案5】:

包装类有效。 MyEntity[] myEnts 不起作用。

这就是我所做的,并且奏效了。

public String createBatch(@PathParam("someParam") String someParam,
                                                  String content)

使用ObjectMapper 转换为对象列表。

List<MyEntity> entities = om.readValue(content, 
                                       new TypeReference<List<MyEntity>>()).

【讨论】:

以上是关于泽西岛,如何发布 JSON 对象列表?的主要内容,如果未能解决你的问题,请参考以下文章

泽西岛的 JSON ArrayList

使用 objectWritter 作为书面类型时的 CORS 响应 - 泽西岛

如何从泽西岛资源生成 JSON?

泽西岛客户端:如何添加列表作为查询参数

邮递员发送的 Json 对象收到空成员

如何解析包含对象列表的 JSON