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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19703540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 19:31:39  来源:igfitidea点击:

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

javajsonspringrestspring-mvc

提问by mannuk

I create the JSON as follows:

我按如下方式创建 JSON:

    var manager = {
        username: "admin",
        password: "admin"
    };
    var userToSubscribe = {
        username: "newuser",
        password: "newpassword",
        email: "[email protected]"
    };

    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":"[email protected]"},"openid":"myopenid"}}  

And I would like to map this JSON to a Wrapper Class. This is the wrapper:

我想将此 JSON 映射到 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 Hymanson dependency in the pom.xml (I'm using spring 3.1.0.RELEASE):

pom.xml 中的 Hymanson 依赖项(我使用的是 spring 3.1.0.RELEASE):

    <dependency>
        <groupId>org.codehaus.Hymanson</groupId>
        <artifactId>Hymanson-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.MappingHymansonHttpMessageConverter">
   <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. Is it possible to do this or do i need to do it with @RequestBodyString or @RequestBody Map<String,Object>and decode the JSON myself?

作为 POST 的结果,我收到 400 Incorrect request 错误。是否可以这样做,或者我是否需要使用@RequestBodyString 或@RequestBody Map<String,Object>自己解码 JSON?

Thanks!

谢谢!

采纳答案by mannuk

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":"[email protected]"},"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. If you build the JSON like this, it will work perfectly:

我稍微改变了它,因为我意识到没有必要创建一个对象订阅和一个 var 订阅。如果您像这样构建 JSON,它将完美运行:

var manager = {
    username: "admin",
    password: "admin"
};
var userToSubscribe = {
    username: "newuser",
    password: "newpassword",
    email: "[email protected]"
};

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...

和订阅包装...

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 MappingHymanson2HttpMessageConverter as Sotirios suggested and there was an exception (No suitable constructor). Hymanson Mapping is not able to build an inner class whether this class is not static. Setting SubscriptionWrapper to static was the solution to my problem.

那么……有什么问题吗?我收到了一个 Incorrect Request 400 错误……我按照 Sotirios 的建议调试了 MappingHymanson2HttpMessageConverter,但出现了一个异常(没有合适的构造函数)。无论此类不是静态的,Hymanson Mapping 都无法构建内部类。将 SubscriptionWrapper 设置为 static 是我问题的解决方案。

You can also check these answers: http://stackoverflow.com/questions/8526333/Hymanson-error-no-suitable-constructor

您还可以查看这些答案: http://stackoverflow.com/questions/8526333/Hymanson-error-no-suitable-constructor

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

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

And if you have problems to deserialize, check this: http://stackoverflow.com/questions/17400850/is-Hymanson-really-unable-to-deserialize-json-into-a-generic-type

如果您有反序列化问题,请检查以下内容: http://stackoverflow.com/questions/17400850/is-Hymanson-really-unable-to-deserialize-json-into-a-generic-type

Thanks for all the replies.

感谢所有的答复。

回答by mvb13

You don't need to do this by yourself. You need to add this dependency in your pom:

你不需要自己做这件事。您需要在 pom 中添加此依赖项:

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

After that Spring will do conversion for you.

之后,Spring 将为您进行转换。

回答by Sotirios Delimanolis

Looking at your JSON

查看您的 JSON

{
    "subscription": {
        "manager": {
            "username": "admin",
            "password": "admin"
        },
        "userToSubscribe": {
            "username": "newuser",
            "password": "newpassword",
            "email": "[email protected]"
        },
        "openid": "myopenid"
    }
}

The root element is subscriptionand it is a JSON object. Your Subscriptionclass doesn't have a subscriptionfield. So there is nothing to map the subscriptionelement to and it therefore fails with a 400 Bad Request.

根元素是subscription并且它是一个 JSON 对象。你的Subscription班级没有subscription字段。所以没有什么可以映射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 ObjectMapperin MappingHymansonHttpMessageConverter(FYI you should be using MappingHymanso2nHttpMessageConverter), so that it ignores missing properties.

您可能需要配置ObjectMapperin MappingHymansonHttpMessageConverter(仅供参考,您应该使用MappingHymanso2nHttpMessageConverter),以便它忽略缺少的属性。