简体   繁体   English

Spring MVC @RequestBody接收具有非原始属性的Object包装器

[英]Spring MVC @RequestBody receive an Object wrapper with non-primitive attributes

I create the JSON as follows: 我按如下方式创建JSON:

    var manager = {
        username: "admin",
        password: "admin"
    };
    var userToSubscribe = {
        username: "newuser",
        password: "newpassword",
        email: "user@1and1.es"
    };

    var openid = "myopenid";

    var subscription = {
            manager: manager,
            userToSubscribe : userToSubscribe,
            openid : openid
    };

    $.ajax({
        url: '/myapp/rest/subscribeUser.json',
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        mimeType: 'application/json',
        data: JSON.stringify({subscription : subscription})   
    });

This is the JSON that is sent: 这是发送的JSON:

{"subscription":{"manager":{"username":"admin","password":"admin"},"userToSubscribe":{"username":"newuser","password":"newpassword","email":"user@1and1.es"},"openid":"myopenid"}}  

And I would like to map this JSON to a Wrapper Class. 我想将这个JSON映射到Wrapper类。 This is the wrapper: 这是包装器:

private class Subscription{
    private User manager;
    private User userToSubscribe;
    private String openid;
    public User getManager() {
        return manager;
    }
    public void setManager(User manager) {
        this.manager = manager;
    }
    public User getUserToSubscribe() {
        return userToSubscribe;
    }
    public void setUserToSubscribe(User userToSubscribe) {
        this.userToSubscribe = userToSubscribe;
    }
    public String getOpenid() {
        return openid;
    }
    public void setOpenid(String openid) {
        this.openid = openid;
    }
}

The jackson dependency in the pom.xml (I'm using spring 3.1.0.RELEASE): pom.xml中的jackson依赖项(我使用的是spring 3.1.0.RELEASE):

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.10</version>
    </dependency>

The mapping in rest-servlet.xml rest-servlet.xml中的映射

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
   <property name="messageConverters">
       <list>
           <ref bean="jsonConverter" />
       </list>
   </property>
</bean>

<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
   <property name="supportedMediaTypes" value="application/json" />
</bean>

And the header of the controller method: 以及控制器方法的标题:

public @ResponseBody SimpleMessage subscribeUser(@RequestBody Subscription subscription)

As a result of the POST I receive a 400 Incorrect request error. 作为POST的结果,我收到400不正确的请求错误。 Is it possible to do this or do i need to do it with @RequestBody String or @RequestBody Map<String,Object> and decode the JSON myself? 是否可以这样做或者我是否需要使用@RequestBody String或@RequestBody Map<String,Object>并自己解码JSON?

Thanks! 谢谢!

Looking at your JSON 看着你的JSON

{
    "subscription": {
        "manager": {
            "username": "admin",
            "password": "admin"
        },
        "userToSubscribe": {
            "username": "newuser",
            "password": "newpassword",
            "email": "user@1and1.es"
        },
        "openid": "myopenid"
    }
}

The root element is subscription and it is a JSON object. 根元素是subscription ,它是一个JSON对象。 Your Subscription class doesn't have a subscription field. 您的Subscription类没有subscription字段。 So there is nothing to map the subscription element to and it therefore fails with a 400 Bad Request. 因此,没有任何内容可以将subscription元素映射到它,因此它会因400 Bad Request而失败。

Create a class SubscriptionWrapper 创建一个类SubscriptionWrapper

public class SubscriptionWrapper {
    private Subscription subscription;

    public Subscription getSubscription() {
        return subscription;
    }

    public void setSubscription(Subscription subscription) {
        this.subscription = subscription;
    }
}

and change your handler method to accept an argument of this type 并更改您的处理程序方法以接受此类型的参数

public @ResponseBody SimpleMessage subscribeUser(@RequestBody SubscriptionWrapper subscriptionWrapper)

You might need to configure the ObjectMapper in MappingJacksonHttpMessageConverter (FYI you should be using MappingJackso2nHttpMessageConverter ), so that it ignores missing properties. 您可能需要在MappingJacksonHttpMessageConverter配置ObjectMapper (您应该使用MappingJackso2nHttpMessageConverter ,因此它会忽略缺少的属性)。

I'm going to answer my own question. 我要回答我自己的问题。 First of all special thanks to Sotirios Delimanolis because he gave me the key in order to investigate what it was happening. 首先要特别感谢Sotirios Delimanolis,因为他给了我钥匙以便调查它发生了什么。

As you know, I create the following json from the view: 如您所知,我从视图中创建了以下json:

{"manager":{"username":"admin","password":"admin"},"userToSubscribe":{"username":"newuser","password":"newpassword","email":"user@1and1.es"},"openid":"https://myopenid..."}

I changed it a little bit because I realised that is not necessary to create a object Subscription and a var Subscription. 我稍微改变了一下,因为我意识到创建对象Subscription和var Subscription不是必需的。 If you build the JSON like this, it will work perfectly: 如果您像这样构建JSON,它将完美地工作:

var manager = {
    username: "admin",
    password: "admin"
};
var userToSubscribe = {
    username: "newuser",
    password: "newpassword",
    email: "user@1and1.es"
};

var openid = "https://myopenid...";

$.ajax({
    url: '/dp/rest/isUserSuscribed.json',
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json',
    mimeType: 'application/json',
    data: JSON.stringify({manager : manager, userToSubscribe : userToSubscribe, openid : openid})   
});

The controller receives this json: 控制器收到这个json:

@RequestMapping(method=RequestMethod.POST, value="/isUserSuscribed.json")
public @ResponseBody ResponseMessageElement<Boolean> isUserSuscribed(@RequestBody SubscriptionWrapper subscription){

And the SubscriptionWrapper... 和SubscriptionWrapper ......

private static class SubscriptionWrapper {
    BasicUser manager;
    BasicUser userToSubscribe;
    String openid;

    public BasicUser getManager() {
        return manager;
    }
    public void setManager(BasicUser manager) {
        this.manager = manager;
    }
    public BasicUser getUserToSubscribe() {
        return userToSubscribe;
    }
    public void setUserToSubscribe(BasicUser userToSubscribe) {
        this.userToSubscribe = userToSubscribe;
    }
    public String getOpenid() {
        return openid;
    }
    public void setOpenid(String openid) {
        this.openid = openid;
    }
}

So... What is the problem? 那么......问题是什么? I was receiving an Incorrect Request 400 error... I debugged the MappingJackson2HttpMessageConverter as Sotirios suggested and there was an exception (No suitable constructor). 我收到了错误的请求400错误...我调试了MappingJackson2HttpMessageConverter作为Sotirios建议并且有一个异常(没有合适的构造函数)。 Jackson Mapping is not able to build an inner class whether this class is not static. Jackson Mapping无法构建内部类,无论此类是否不是静态的。 Setting SubscriptionWrapper to static was the solution to my problem. 将SubscriptionWrapper设置为static是解决我的问题的方法。

You can also check these answers: http://stackoverflow.com/questions/8526333/jackson-error-no-suitable-constructor 您还可以查看以下答案: http://stackoverflow.com/questions/8526333/jackson-error-no-suitable-constructorhttp://stackoverflow.com/questions/8526333/jackson-error-no-suitable-constructor

http://stackoverflow.com/questions/12139380/how-to-convert-json-into-pojo-in-java-using-jackson

And if you have problems to deserialize, check this: http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type 如果你有反序列化的问题,请检查: http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-typehttp://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type

Thanks for all the replies. 感谢所有的答复。

You don't need to do this by yourself. 你不需要自己做这件事。 You need to add this dependency in your pom: 您需要在pom中添加此依赖项:

<dependencies>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.8.5</version>
    </dependency>
  </dependencies>

After that Spring will do conversion for you. 之后春天会为你做转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM