2013-10-31 30 views
7

對象包裝我創建JSON如下:Spring MVC的@RequestBody收到非原始屬性

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}) 
    }); 

這是發送的JSON:

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

,我想將這個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; 
    } 
} 

傑克遜依賴性在pom.xml(我使用彈簧3.1.0.RELEASE):

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

在休息-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> 

而控制器方法的報頭:

public @ResponseBody SimpleMessage subscribeUser(@RequestBody Subscription subscription) 

作爲POST的結果,我收到400錯誤的請求錯誤。是否有可能這樣做,或者我需要使用@RequestBody字符串還是@RequestBody Map<String,Object>來完成,並自己解碼JSON?

謝謝!

+0

應該沒有什麼阻止你這樣做。錯誤400表示請求或映射有問題。 'User'類是否有默認的無參數構造函數。 –

+0

這個包裝器在Java中是一個絕對不同的概念,你有幾個想要在外部類中聚合的對象。 – 2013-10-31 11:12:38

+0

你使用的是什麼版本的彈簧? –

回答

3

我要回答我自己的問題。首先要特別感謝Sotirios Delimanolis,因爲他給了我鑰匙,以便調查它發生了什麼。

如你所知,我從視圖中創建以下JSON:

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

我改變一點點,因爲我意識到這是沒有必要創建一個對象申購和一個變種訂閱。如果你建立這樣的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}) 
}); 

控制器接收此JSON:

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

而且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; 
    } 
} 

所以...問題是什麼?我收到一個錯誤的請求400錯誤...我調試MappingJackson2HttpMessageConverter作爲Sotirios建議,並且有一個異常(沒有合適的構造函數)。傑克遜映射不能建立一個內部類,不管這個類是不是靜態的。將SubscriptionWrapper設置爲靜態是我的問題的解決方案。

您還可以查看這些問題的答案: http://stackoverflow.com/questions/8526333/jackson-error-no-suitable-constructor

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

如果你有問題,反序列化,檢查: http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type

感謝所有的答覆。

2

你不需要自己做。你需要在你的pom中添加這個依賴:

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

之後,Spring會爲你做轉換。在你的JSON

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

根元素是subscription

+0

是的,我有依賴。它工作,如果我只發送用戶有用戶名,密碼...但如果我嘗試發送訂閱對象未映射。因此,如果訂閱包裝器不起作用,一種方法是ResponseBody String或ResponseBody Map ,並自己獲取元素並轉換爲我的對象。 – mannuk

+0

我不明白一個細節。你說當你只發送用戶對象(你把它發送給另一個網址?)它可以工作,但是當你發送整個訂閱時這是行不通的。它是否正確?如果是,請先嚐試檢查映射URL,然後將HTTP請求Content-Type指定爲json第二。 – mvb13

+0

你能否詳細說明春天是如何做到的。是唯一的傑克遜集成可以將其轉換爲JSON格式。 OP期望用'@ ResponseBody'填充模型。 – 2013-10-31 11:19:49

10

看,這是一個JSON對象。您的Subscription類沒有subscription字段。因此沒有任何東西可以映射subscription元素,因此它會因400錯誤請求而失敗。

創建一個類SubscriptionWrapper

public class SubscriptionWrapper { 
    private Subscription subscription; 

    public Subscription getSubscription() { 
     return subscription; 
    } 

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

,改變你的處理方法來接受這種類型的參數

public @ResponseBody SimpleMessage subscribeUser(@RequestBody SubscriptionWrapper subscriptionWrapper) 

您可能需要配置ObjectMapperMappingJacksonHttpMessageConverter(FYI,你應該使用MappingJackso2nHttpMessageConverter ),以便它忽略缺少的屬性。

+0

你想介紹一下你最後的幾行嗎? ObjectMapper和MappingJackson2HttpMessageConverter的配置。在我的情況下,對象由於沒有必要而缺少屬性。 – mannuk

+0

@mannuk'MappingJackson2HttpMessageConverter'使用包含「com.fasterxml.jackson」包的新的Jackson庫。 'ObjectMapper'有一個'configure()'方法,您可以使用它來配置反序列化和序列化功能。你可能想看看其中的一些。 –

+0

你知道我可以檢查它的任何網站嗎?我想了解更多關於轉換器和配置方法。我會在星期一在工作中測試你的答案,然後我可以告訴你我的進展 – mannuk