JAX-RS 发布多个对象

发布于 2024-10-30 08:07:58 字数 224 浏览 3 评论 0原文

我有一个方法;

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(ObjectOne objectOne, ObjectTwo objectTwo)

现在我知道我可以以 json 格式发布单个对象,只需将其放入正文中即可。 但是可以做多个对象吗?如果是这样,怎么办?

I have a method;

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(ObjectOne objectOne, ObjectTwo objectTwo)

Now I know I can post a single object in json format, just putting it into the body.
But is it possible to do multiple objects? If so, how?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

绳情 2024-11-06 08:07:58

正如 Tarlog 所正确指出的那样,您不能使用您的方法。

但是,您可以这样做:

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(List<ObjectOne> objects)

或这样做:

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(BeanWithObjectOneAndObjectTwo containerObject)

此外,您始终可以将您的方法与 GET 参数结合起来:

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(List<ObjectOne> objects, @QueryParam("objectTwoId") long objectTwoId)

You can not use your method like this as correctly stated by Tarlog.

However, you can do this:

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(List<ObjectOne> objects)

or this:

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(BeanWithObjectOneAndObjectTwo containerObject)

Furthermore, you can always combine your method with GET parameters:

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(List<ObjectOne> objects, @QueryParam("objectTwoId") long objectTwoId)
九公里浅绿 2024-11-06 08:07:58

答案是

原因很简单:这是关于您可以在方法中接收的参数。它们必须与请求相关。正确的?因此它们必须是 headers 或 cookie 或查询参数或矩阵参数或路径参数或请求正文。 (为了讲述完整的故事,还有称为上下文的其他类型的参数)。

现在,当您在请求中收到 JSON 对象时,您会在请求正文中收到它。该请求可能有多少个主体?唯一的一个。所以你只能接收一个 JSON 对象。

The answer is no.

The reason is simple: This about the parameters you can receive in a method. They must be related to the request. Right? So they must be either headers or cookies or query parameters or matrix parameters or path parameters or request body. (Just to tell the complete story there is additional types of parameters called context).

Now, when you receive JSON object in your request, you receive it in a request body. How many bodies the request may have? One and only one. So you can receive only one JSON object.

一生独一 2024-11-06 08:07:58

如果我们看看 OP 试图做什么,他/她正在尝试发布两个(可能不相关的)JSON 对象。首先,任何尝试将一部分作为正文发送,并将一部分作为其他参数发送的解决方案,IMO,都是可怕的解决方案。 POST 数据应该放在正文中。仅仅因为某件事有效就去做它是不对的。某些解决方法可能违反基本的 REST 原则。

我看到一些解决方案

  1. 使用 application/x-www-form-urlencoded
  2. 使用 Multipart
  3. 只需将它们包装在单个父对象中

1. 使用 application/x-www-form-urlencoded

另一种选择是仅使用 application/x- www-form-urlencoded。我们实际上可以拥有 JSON 值。例如,要

curl -v http://localhost:8080/api/model \
     -d 'one={"modelOne":"helloone"}' \
     -d 'two={"modelTwo":"hellotwo"}'

public class ModelOne {
    public String modelOne;
}

public class ModelTwo {
    public String modelTwo;
}

@Path("model")
public class ModelResource {

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public String post(@FormParam("one") ModelOne modelOne,
                       @FormParam("two") ModelTwo modelTwo) {
        return modelOne.modelOne + ":" + modelTwo.modelTwo;
    }
}

使其正常工作,我们需要的一件事是使用 ParamConverterProvider 才能使其正常工作。下面是 Jersey 团队的 Michal Gadjos 实现的一个(发现 此处有解释)。

@Provider
public class JacksonJsonParamConverterProvider implements ParamConverterProvider {

    @Context
    private Providers providers;

    @Override
    public <T> ParamConverter<T> getConverter(final Class<T> rawType,
                                              final Type genericType,
                                              final Annotation[] annotations) {
        // Check whether we can convert the given type with Jackson.
        final MessageBodyReader<T> mbr = providers.getMessageBodyReader(rawType,
                genericType, annotations, MediaType.APPLICATION_JSON_TYPE);
        if (mbr == null
              || !mbr.isReadable(rawType, genericType, annotations, MediaType.APPLICATION_JSON_TYPE)) {
            return null;
        }

        // Obtain custom ObjectMapper for special handling.
        final ContextResolver<ObjectMapper> contextResolver = providers
                .getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE);

        final ObjectMapper mapper = contextResolver != null ?
                contextResolver.getContext(rawType) : new ObjectMapper();

        // Create ParamConverter.
        return new ParamConverter<T>() {

            @Override
            public T fromString(final String value) {
                try {
                    return mapper.reader(rawType).readValue(value);
                } catch (IOException e) {
                    throw new ProcessingException(e);
                }
            }

            @Override
            public String toString(final T value) {
                try {
                    return mapper.writer().writeValueAsString(value);
                } catch (JsonProcessingException e) {
                    throw new ProcessingException(e);
                }
            }
        };
    }
}

如果您不扫描资源和提供程序,只需注册该提供程序,上面的示例就应该可以工作。

2.使用Multipart

没有人提到的一种解决方案是使用

此处)

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>${jersey-2.x.version}</version>
</dependency>

这是一个使用 Jersey 的示例(请参阅官方文档 MultipartFeature

import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("/api")
public class JerseyApplication extends ResourceConfig {

    public JerseyApplication() {
        packages("stackoverflow.jersey");
        register(MultiPartFeature.class);
    }
}

资源类

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.media.multipart.FormDataParam;

@Path("foobar")
public class MultipartResource {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response postFooBar(@FormDataParam("foo") Foo foo,
                               @FormDataParam("bar") Bar bar) {
        String response = foo.foo + "; " + bar.bar;
        return Response.ok(response).build();
    }

    public static class Foo {
        public String foo;
    }

    public static class Bar {
        public String bar;
    }
}

现在,对于某些客户端来说,棘手的部分是没有办法设置每个正文部分的 Content-Type,而这是上述内容所必需的工作。多部分提供程序将根据每个部分的类型查找消息正文阅读器。如果它没有设置为 application/json 或类型,FooBar 有一个阅读器,这将会失败。我们将在这里使用 JSON。除了有一个可用的阅读器之外,没有额外的配置。我会用杰克逊。使用以下依赖项,不需要其他配置,因为将通过类路径扫描发现提供程序。

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey-2.x.version}</version>
</dependency>

现在测试。我将使用 cURL。您可以看到我使用 type 为每个部分显式设置了 Content-Type-F 表示不同的部分。 (请参阅帖子的最底部,了解请求正文的实际外观。)

curl -v -X POST \
-H“内容类型:多部分/表单数据”\
-F "bar={\"bar\":\"BarBar\"};type=application/json" \
-F "foo={\"foo\":\"FooFoo\"};type=application/json" \
http://localhost:8080/api/foobar

结果: FooFoo;酒吧酒吧

结果完全符合我们的预期。如果您查看资源方法,我们所做的就是返回从两个 JSON 对象收集的字符串 foo.foo + "; " + bar.bar

您可以在下面的链接中看到一些使用不同 JAX-RS 客户端的示例。您还将看到来自这些不同 JAX-RS 实现的一些服务器端示例。每个链接中都应该有一个指向该实现的官方文档的链接

还有其他 JAX-RS那里有实现,但您需要自己找到它的文档。以上三个是我唯一有经验的。

就 Javascript 客户端而言,我看到的大多数示例(例如 其中一些 涉及设置 Content-Type 为 undefined/false(使用 FormData),让浏览器处理它,但这对我们不起作用,因为浏览器不会设置 Content-Type。 部分的默认类型是 text/plain

每个 手动,我将发布一个示例(从 此处 获得一些帮助。我将使用 Angular,但是 grunt构建实体主体的工作将是普通的旧 Javascript。

<!DOCTYPE html>
<html ng-app="multipartApp">
    <head>
        <script src="js/libs/angular.js/angular.js"></script>
        <script>
            angular.module("multipartApp", [])
            .controller("defaultCtrl", function($scope, $http) {

                $scope.sendData = function() {
                    var foo = JSON.stringify({foo: "FooFoo"});
                    var bar = JSON.stringify({bar: "BarBar"});

                    var boundary = Math.random().toString().substr(2);                    
                    var header = "multipart/form-data; charset=utf-8; boundary=" + boundary;

                    $http({
                        url: "/api/foobar",
                        headers: { "Content-Type": header }, 
                        data: createRequest(foo, bar, boundary),
                        method: "POST"
                    }).then(function(response) {
                        $scope.result = response.data;
                    });
                };

                function createRequest(foo, bar, boundary) {
                    var multipart = "";
                    multipart += "--" + boundary
                        + "\r\nContent-Disposition: form-data; name=foo"
                        + "\r\nContent-type: application/json"
                        + "\r\n\r\n" + foo + "\r\n";        
                    multipart += "--" + boundary
                        + "\r\nContent-Disposition: form-data; name=bar"
                        + "\r\nContent-type: application/json"
                        + "\r\n\r\n" + bar + "\r\n";
                    multipart += "--" + boundary + "--\r\n";
                    return multipart;
                }
            });
        </script>
    </head>
    <body>
        <div ng-controller="defaultCtrl">
            <button ng-click="sendData()">Send</button>
            <p>{{result}}</p>
        </div>
    </body>
</html>

有趣的部分是 createRequest 函数,这是我们构建多部分的地方,设置每个部分的 Content-Type 。到 application/json,并将字符串化的 foobar 对象连接到每个部分。如果您不熟悉多部分格式请参阅此处了解更多信息。另一个有趣的部分是标题。我们将其设置为multipart/form-data

下面是结果。在 Angular 中,我只是使用 $scope.result = response.data 在 HTML 中显示结果。您看到的按钮只是提出请求。您还将在 firebug

在此处输入图像描述

3. 只需将它们包装在单个父对象中

此选项应该是不言自明的,正如其他人已经提到的那样。

If we look at what the OP is trying to do, he/she is trying to post two (possibly unrelated) JSON objects. First any solution to try and send one part as the body, and one part as some other param, IMO, are horrible solutions. POST data should go in the body. It's not right to do something just because it works. Some work-arounds might be violating basic REST principles.

I see a few solutions

  1. Use application/x-www-form-urlencoded
  2. Use Multipart
  3. Just wrap them in a single parent object

1. Use application/x-www-form-urlencoded

Another option is to just use application/x-www-form-urlencoded. We can actually have JSON values. For examle

curl -v http://localhost:8080/api/model \
     -d 'one={"modelOne":"helloone"}' \
     -d 'two={"modelTwo":"hellotwo"}'

public class ModelOne {
    public String modelOne;
}

public class ModelTwo {
    public String modelTwo;
}

@Path("model")
public class ModelResource {

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public String post(@FormParam("one") ModelOne modelOne,
                       @FormParam("two") ModelTwo modelTwo) {
        return modelOne.modelOne + ":" + modelTwo.modelTwo;
    }
}

The one thing we need to get this to work is a ParamConverterProvider to get this to work. Below is one that has been implemented by Michal Gadjos of the Jersey Team (found here with explanation).

@Provider
public class JacksonJsonParamConverterProvider implements ParamConverterProvider {

    @Context
    private Providers providers;

    @Override
    public <T> ParamConverter<T> getConverter(final Class<T> rawType,
                                              final Type genericType,
                                              final Annotation[] annotations) {
        // Check whether we can convert the given type with Jackson.
        final MessageBodyReader<T> mbr = providers.getMessageBodyReader(rawType,
                genericType, annotations, MediaType.APPLICATION_JSON_TYPE);
        if (mbr == null
              || !mbr.isReadable(rawType, genericType, annotations, MediaType.APPLICATION_JSON_TYPE)) {
            return null;
        }

        // Obtain custom ObjectMapper for special handling.
        final ContextResolver<ObjectMapper> contextResolver = providers
                .getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE);

        final ObjectMapper mapper = contextResolver != null ?
                contextResolver.getContext(rawType) : new ObjectMapper();

        // Create ParamConverter.
        return new ParamConverter<T>() {

            @Override
            public T fromString(final String value) {
                try {
                    return mapper.reader(rawType).readValue(value);
                } catch (IOException e) {
                    throw new ProcessingException(e);
                }
            }

            @Override
            public String toString(final T value) {
                try {
                    return mapper.writer().writeValueAsString(value);
                } catch (JsonProcessingException e) {
                    throw new ProcessingException(e);
                }
            }
        };
    }
}

If you aren't scanning for resource and providers, just register this provider, and the above example should work.

2. Use Multipart

One solution that no one has mentioned, is to use multipart. This allows us to send arbitrary parts in a request. Since each request can only have one entity body, multipart is the work around, as it allows to have different parts (with their own content types) as part of the entity body.

Here is an example using Jersey (see official doc here)

Dependency

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>${jersey-2.x.version}</version>
</dependency>

Register the MultipartFeature

import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("/api")
public class JerseyApplication extends ResourceConfig {

    public JerseyApplication() {
        packages("stackoverflow.jersey");
        register(MultiPartFeature.class);
    }
}

Resource class

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.media.multipart.FormDataParam;

@Path("foobar")
public class MultipartResource {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response postFooBar(@FormDataParam("foo") Foo foo,
                               @FormDataParam("bar") Bar bar) {
        String response = foo.foo + "; " + bar.bar;
        return Response.ok(response).build();
    }

    public static class Foo {
        public String foo;
    }

    public static class Bar {
        public String bar;
    }
}

Now the tricky part with some clients is that there isn't a way to set the Content-Type of each body part, which is required for the above to work. The multipart provider will look up message body reader, based on the type of each part. If it's not set to application/json or a type, the Foo or Bar has a reader for, this will fail. We will use JSON here. There's no extra configuration but to have a reader available. I'll use Jackson. With the below dependency, no other configuration should be required, as the provider will be discovered through classpath scanning.

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey-2.x.version}</version>
</dependency>

Now the test. I will be using cURL. You can see I explicitly set the Content-Type for each part with type. The -F signifies to different part. (See very bottom of the post for an idea of how the request body actually looks.)

curl -v -X POST \
-H "Content-Type:multipart/form-data" \
-F "bar={\"bar\":\"BarBar\"};type=application/json" \
-F "foo={\"foo\":\"FooFoo\"};type=application/json" \
http://localhost:8080/api/foobar

Result: FooFoo; BarBar

The result is exactly as we expected. If you look at the resource method, all we do is return this string foo.foo + "; " + bar.bar, gathered from the two JSON objects.

You can see some examples using some different JAX-RS clients, in the links below. You will also see some server side example also from those different JAX-RS implementations. Each link should have somewhere in it a link to the official documentation for that implementation

There are other JAX-RS implementations out there, but you will need to find the documentation for it yourself. The above three are the only ones I have experience with.

As far as Javascript clients, most of the example I see (e.g. some of these involve setting the Content-Type to undefined/false (using FormData), letting the Browser handle the it. But this will not work for us, as the Browser will not set the Content-Type for each part. And the default type is text/plain.

I'm sure there are libraries out there that allow setting the type for each part, but just to show you how it can be done manually, I'll post an example (got a little help from here. I'll be using Angular, but the grunt work of building the entity body will be plain old Javascript.

<!DOCTYPE html>
<html ng-app="multipartApp">
    <head>
        <script src="js/libs/angular.js/angular.js"></script>
        <script>
            angular.module("multipartApp", [])
            .controller("defaultCtrl", function($scope, $http) {

                $scope.sendData = function() {
                    var foo = JSON.stringify({foo: "FooFoo"});
                    var bar = JSON.stringify({bar: "BarBar"});

                    var boundary = Math.random().toString().substr(2);                    
                    var header = "multipart/form-data; charset=utf-8; boundary=" + boundary;

                    $http({
                        url: "/api/foobar",
                        headers: { "Content-Type": header }, 
                        data: createRequest(foo, bar, boundary),
                        method: "POST"
                    }).then(function(response) {
                        $scope.result = response.data;
                    });
                };

                function createRequest(foo, bar, boundary) {
                    var multipart = "";
                    multipart += "--" + boundary
                        + "\r\nContent-Disposition: form-data; name=foo"
                        + "\r\nContent-type: application/json"
                        + "\r\n\r\n" + foo + "\r\n";        
                    multipart += "--" + boundary
                        + "\r\nContent-Disposition: form-data; name=bar"
                        + "\r\nContent-type: application/json"
                        + "\r\n\r\n" + bar + "\r\n";
                    multipart += "--" + boundary + "--\r\n";
                    return multipart;
                }
            });
        </script>
    </head>
    <body>
        <div ng-controller="defaultCtrl">
            <button ng-click="sendData()">Send</button>
            <p>{{result}}</p>
        </div>
    </body>
</html>

The interesting part is the createRequest function. This is where we build the multipart, setting the Content-Type of each part to application/json, and concatenating the stringified foo and bar objects to each part. If you are unfamiliar multipart format see here for more info. The other interesting part is the header. We set it to multipart/form-data.

Below is the result. In Angular I just used the result to show in the HTML, with $scope.result = response.data. The button you see was just to make the request. You will also see the request data in firebug

enter image description here

3. Just wrap them in a single parent object

This option should be self explanatory, as others have already mentioned.

清秋悲枫 2024-11-06 08:07:58

在这种情况下通常采用下一种方法:

TransferObject {
    ObjectOne objectOne;
    ObjectTwo objectTwo;

    //getters/setters
}

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(TransferObject object){
//        object.getObejctOne()....
}

The next approach is usually applied in this kind of cases:

TransferObject {
    ObjectOne objectOne;
    ObjectTwo objectTwo;

    //getters/setters
}

@POST
@Path("test")
@Consumes(MediaType.APPLICATION_JSON)
public void test(TransferObject object){
//        object.getObejctOne()....
}
无声无音无过去 2024-11-06 08:07:58

正如 Tarlog 所解释的,您不能将两个单独的对象放入一个 POST 调用中。

无论如何,您可以创建包含前两个对象的第三个容器对象,并在 POS 调用中传递该对象。

You can't put two separate objects in one single POST call as explained by Tarlog.

Anyway you could create a third container object that contains the first two objects and pass that one within the POS call.

沙沙粒小 2024-11-06 08:07:58

我也面临过这些问题。也许这会有所帮助。

@POST
@Path("/{par}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Object centralService(@PathParam("par") String operation, Object requestEntity) throws JSONException {

    ObjectMapper objectMapper=new ObjectMapper();

    Cars cars = new Cars();  
    Seller seller = new Seller();
    String someThingElse;

    HashMap<String, Object> mapper = new HashMap<>(); //Diamond )))

    mapper = (HashMap<String, Object>) requestEntity;

    cars=objectMapper.convertValue(mapper.get("cars"), Cars.class);
    seller=objectMapper.convertValue(mapper.get("seller"), Seller.class);
    someThingElse=objectMapper.convertValue(mapper.get("someThingElse"), String.class);

    System.out.println("Cars Data "+cars.toString());

    System.out.println("Sellers Data "+seller.toString());

    System.out.println("SomeThingElse "+someThingElse);

    if (operation.equals("search")) {
        System.out.println("Searching");
    } else if (operation.equals("insertNewData")) {
        System.out.println("Inserting New Data");
    } else if (operation.equals("buyCar")) {
        System.out.println("Buying new Car");
    }

    JSONObject json=new JSONObject();
    json.put("result","Works Fine!!!");


    return json.toString();

}


*******CARS POJO********@XmlRootElement for Mapping Object to XML or JSON***

@XmlRootElement
public class Cars {
    private int id;
    private String brand;
    private String model;
    private String body_type;
    private String fuel;
    private String engine_volume;
    private String horsepower;
    private String transmission;
    private String drive;
    private String status;
    private String mileage;
    private String price;
    private String description;
    private String picture;
    private String fk_seller_oid;
    } // Setters and Getters Omitted 

*******SELLER POJO********@XmlRootElement for Mapping Object to XML or JSON***

@XmlRootElement
public class Seller {
    private int id;
    private String name;
    private String surname;
    private String phone;
    private String email;
    private String country;
    private String city;
    private String paste_date;
    }//Setters and Getters omitted too


*********************FRONT END Looks Like This******************

$(function(){
$('#post').on('click',function(){
        console.log('Begins');
        $.ajax({
            type:'POST',
            url: '/ENGINE/cars/test',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data:complexObject(),
            success: function(data){
                console.log('Sended and returned'+JSON.stringify(data));
            },
            error: function(err){
                console.log('Error');
                console.log("AJAX error in request: " + JSON.stringify(err, null, 2));
            }
        }); //-- END of Ajax
        console.log('Ends POST');
        console.log(formToJSON());

    }); // -- END of click function   POST


function complexObject(){
    return JSON.stringify({
                "cars":{"id":"1234","brand":"Mercedes","model":"S class","body_type":"Sedan","fuel":"Benzoline","engine_volume":"6.5",
                "horsepower":"1600","transmission":"Automat","drive":"Full PLag","status":"new","mileage":"7.00","price":"15000",
                "description":"new car and very nice car","picture":"mercedes.jpg","fk_seller_oid":"1234444"},
        "seller":{  "id":"234","name":"Djonotan","surname":"Klinton","phone":"+994707702747","email":"[email protected]",                 "country":"Azeribaijan","city":"Baku","paste_date":"20150327"},
        "someThingElse":"String type of element"        
    }); 
} //-- END of Complex Object
});// -- END of JQuery -  Ajax

I have also faced with these problem. Maybe this will help.

@POST
@Path("/{par}")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Object centralService(@PathParam("par") String operation, Object requestEntity) throws JSONException {

    ObjectMapper objectMapper=new ObjectMapper();

    Cars cars = new Cars();  
    Seller seller = new Seller();
    String someThingElse;

    HashMap<String, Object> mapper = new HashMap<>(); //Diamond )))

    mapper = (HashMap<String, Object>) requestEntity;

    cars=objectMapper.convertValue(mapper.get("cars"), Cars.class);
    seller=objectMapper.convertValue(mapper.get("seller"), Seller.class);
    someThingElse=objectMapper.convertValue(mapper.get("someThingElse"), String.class);

    System.out.println("Cars Data "+cars.toString());

    System.out.println("Sellers Data "+seller.toString());

    System.out.println("SomeThingElse "+someThingElse);

    if (operation.equals("search")) {
        System.out.println("Searching");
    } else if (operation.equals("insertNewData")) {
        System.out.println("Inserting New Data");
    } else if (operation.equals("buyCar")) {
        System.out.println("Buying new Car");
    }

    JSONObject json=new JSONObject();
    json.put("result","Works Fine!!!");


    return json.toString();

}


*******CARS POJO********@XmlRootElement for Mapping Object to XML or JSON***

@XmlRootElement
public class Cars {
    private int id;
    private String brand;
    private String model;
    private String body_type;
    private String fuel;
    private String engine_volume;
    private String horsepower;
    private String transmission;
    private String drive;
    private String status;
    private String mileage;
    private String price;
    private String description;
    private String picture;
    private String fk_seller_oid;
    } // Setters and Getters Omitted 

*******SELLER POJO********@XmlRootElement for Mapping Object to XML or JSON***

@XmlRootElement
public class Seller {
    private int id;
    private String name;
    private String surname;
    private String phone;
    private String email;
    private String country;
    private String city;
    private String paste_date;
    }//Setters and Getters omitted too


*********************FRONT END Looks Like This******************

$(function(){
$('#post').on('click',function(){
        console.log('Begins');
        $.ajax({
            type:'POST',
            url: '/ENGINE/cars/test',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data:complexObject(),
            success: function(data){
                console.log('Sended and returned'+JSON.stringify(data));
            },
            error: function(err){
                console.log('Error');
                console.log("AJAX error in request: " + JSON.stringify(err, null, 2));
            }
        }); //-- END of Ajax
        console.log('Ends POST');
        console.log(formToJSON());

    }); // -- END of click function   POST


function complexObject(){
    return JSON.stringify({
                "cars":{"id":"1234","brand":"Mercedes","model":"S class","body_type":"Sedan","fuel":"Benzoline","engine_volume":"6.5",
                "horsepower":"1600","transmission":"Automat","drive":"Full PLag","status":"new","mileage":"7.00","price":"15000",
                "description":"new car and very nice car","picture":"mercedes.jpg","fk_seller_oid":"1234444"},
        "seller":{  "id":"234","name":"Djonotan","surname":"Klinton","phone":"+994707702747","email":"[email protected]",                 "country":"Azeribaijan","city":"Baku","paste_date":"20150327"},
        "someThingElse":"String type of element"        
    }); 
} //-- END of Complex Object
});// -- END of JQuery -  Ajax
还不是爱你 2024-11-06 08:07:58

这可以通过声明 POST 方法来接受对象数组来完成。像这样的例子

T[] create(@RequestBody T[] objects) {
for( T object : objects ) {
   service.create(object);
  }
}

It can be done by having the POST method declared to accept array of objects. Example like this

T[] create(@RequestBody T[] objects) {
for( T object : objects ) {
   service.create(object);
  }
}
女皇必胜 2024-11-06 08:07:58

更改@Consumes(MediaType.APPLICATION_JSON)
到@Consumes({MediaType.APPLICATION_FORM_URLENCODED})
然后你可以将多个对象放入body中

Change @Consumes(MediaType.APPLICATION_JSON)
to @Consumes({MediaType.APPLICATION_FORM_URLENCODED})
Then you can putting multiple objects into the body

找回味觉 2024-11-06 08:07:58

我的解决方案是为CXF编写的,看起来很简单。

import org.apache.cxf.jaxrs.ext.multipart.Multipart;

@POST
@Path("paramTest")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public GenericResult paramTest(
    @Multipart(value = "myData", type=MediaType.APPLICATION_JSON)
        ObjectOne myData,
    @Multipart(value = "infoList", type=MediaType.APPLICATION_JSON)
        ObjectTwo[] infoList);

使用 io.restassurred 的测试代码:

@Test
public void paramTest()
{
    String payload1 = "" +
        "{ \"name\": \"someName\", \"branch\": \"testBranch\" }";
    String payload2 =
        " [ { \"name\": \"cn\", \"status\": \"ts\" }," +
            "{ \"name\": \"cn2\", \"status\": \"ts2\" } ] ]";
    RestAssured.
    given().
    contentType("multipart/form-data").
        multiPart("myData", payload1, "application/json").
        multiPart("infoList", payload2, "application/json").
    post(String.format("%s/paramTest", API_PATH)).
    then().
    statusCode(HttpStatus.SC_OK).
    contentType(ContentType.JSON).
    body("success", Matchers.equalTo(true));
}

My solution is written for CXF, it appears to be quite simple.

import org.apache.cxf.jaxrs.ext.multipart.Multipart;

@POST
@Path("paramTest")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public GenericResult paramTest(
    @Multipart(value = "myData", type=MediaType.APPLICATION_JSON)
        ObjectOne myData,
    @Multipart(value = "infoList", type=MediaType.APPLICATION_JSON)
        ObjectTwo[] infoList);

The test code for this with io.restassurred:

@Test
public void paramTest()
{
    String payload1 = "" +
        "{ \"name\": \"someName\", \"branch\": \"testBranch\" }";
    String payload2 =
        " [ { \"name\": \"cn\", \"status\": \"ts\" }," +
            "{ \"name\": \"cn2\", \"status\": \"ts2\" } ] ]";
    RestAssured.
    given().
    contentType("multipart/form-data").
        multiPart("myData", payload1, "application/json").
        multiPart("infoList", payload2, "application/json").
    post(String.format("%s/paramTest", API_PATH)).
    then().
    statusCode(HttpStatus.SC_OK).
    contentType(ContentType.JSON).
    body("success", Matchers.equalTo(true));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文