【问题标题】:Unmarshalling different objects in same Jersey service [duplicate]在同一泽西岛服务中解组不同的对象[重复]
【发布时间】:2025-12-04 06:10:01
【问题描述】:

我正在尝试找到一种方法来创建一个服务,该服务将接收不同的对象类型作为 JSON 并正确解组它们。到目前为止,我能够使用自定义解串器和谷歌的 gson 库来实现单个或列表对象解组,但这确实是有限的。我可以使用它创建的唯一服务类型只能将单一类型的对象作为参数,如下所示:

@GET
@Path("myService")
@Consumes(MediaType.APPLICATION_JSON)
public Response myService(MyEntity entity) {
    //Random stuff using entity
    return Response.ok().build();
}

但是我正在尝试创建这样的服务:

@GET
@Path("advancedService")
@Consumes(MediaType.APPLICATION_JSON)
public Response advancedService(MyEntity1 entity1, MyEntity2 entity2, @QueryParam("normalParam") int normalParam, @QueryParam("normalBoolean") boolean normalBoolean) {
    //Do stuff using both entity1 and entity2.
    return Response.ok().build();
}

现在,当我通过 ajax 请求发送 JSON 时,为了让服务理解对象结构,它必须像这样格式化:

$.ajax({
    url: 'services/MyServices/myService',
    type: 'GET',
    data: JSON.stringify(myEntityObjectStructure),
    contentType: 'application/json; charset=UTF-8',
    dataType: 'json',
    success: function (result, status, xhr) {
      //blahblah
    }
  });

data 配置中,它只需要读取对象结构,否则会混淆。我正在尝试发送这样的请求:

$.ajax({
    url: 'services/MyServices/myService',
    type: 'GET',
    data: {
        myEntity1: JSON.stringify(myEntity1ObjectStructure),
        myEntity2: JSON.stringify(myEntity2ObjectStructure),
        normalParam: param1,
        booleanParam: param2
    },
    contentType: 'application/json; charset=UTF-8',
    dataType: 'json',
    success: function (result, status, xhr) {
      //blahblah
    }
  });

但它只是不会读取参数名称并且卡住了,因为它认为它必须将所有 data 结构解组为单个对象。

我正在使用球衣 2.19。此外,我正在寻找一个正常的解决方案,而不是一个“hacky”的解决方案。我也可以将对象作为“字符串”发送并自己解组,但我想坚持使用注释并使用自定义序列化程序或某种类型的 web.xml 配置来处理(un)编组的服务标准.我喜欢使用 gson 的简单性(尤其是日期格式,并且不需要注释以排除字段等),但我也愿意使用 Jackson

编辑:它也可以是 POST 类型的服务,我只需要它有 2 个不同的类作为参数。

【问题讨论】:

    标签: java ajax json jersey marshalling


    【解决方案1】:

    在我看来,最漂亮的解决方案是创建一个父对象,包含您要传输的所有内容。

    @XmlRootElement
    class AdvancedServiceInput {
        public MyEntity1 entity1;
        public MyEntity2 entity2;
    }
    

    然后通过接受容器对象来接收数据:

    @GET
    @Path("advancedService")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response advancedService(AdvancedServiceInput input, @QueryParam("normalParam") int normalParam, @QueryParam("normalBoolean") boolean normalBoolean) {
        //Do stuff using both input.entity1 and input.entity2.
        return Response.ok().build();
    }
    

    是什么让这个解决方案美丽

    • 通常更少的参数提高了可读性。拥有具有大量参数的方法使得难以识别哪个参数用于哪个目标。 (特别是因为 java 不允许命名参数)
    • 拥有容器使您的代码更容易扩展。如果您想添加第三种实体类型,您只需扩展您的容器类,而无需更改(大量)方法签名。
    • XML 和 JSON 内容应该只包含 一个,单个根元素。因此,无论如何您可能都必须使用这种方法来创建有效的传输消息。

    【讨论】:

    • 正如我所说,我不是在寻找“hacky”解决方案。将我的项目与随机对象混为一谈只是为了解决问题并不是解决方案。正如我所说,我可以使用 json 字符串实现我正在寻找的东西,但这不是问题的重点。甚至可以在一个服务方法中拥有 2 种不同类型的对象???
    • @Konstantine 这是我能想象到的最漂亮的解决方案。但是让我们看一下 - 也许其他人发布了一个更漂亮的答案。
    • 很明显,从重复的帖子中可以看出,服务并不意味着接收不同类型的对象。必须想办法绕过这个限制......