2013-10-31 3 views
7

ich die JSON erstellen wie folgt:Spring MVC @RequestBody erhalten eine Objekt-Wrapper mit nicht-primitive Attribute

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

Dies ist die JSON, die gesendet wird:

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

Und ich möchte Ordnen Sie diesen JSON einer Wrapper-Klasse zu. Dies ist der 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; 
    } 
} 

Die jackson Abhängigkeit in der pom.xml (Ich bin mit Feder 3.1.0.RELEASE):

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

Die Abbildung in 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> 

Und der Kopf der Controller-Methode:

public @ResponseBody SimpleMessage subscribeUser(@RequestBody Subscription subscription) 

Als Ergebnis des POST erhalte ich einen Fehler 400 falsche Anfrage. Ist es möglich, dies zu tun oder muss ich es mit @RequestBody String oder @RequestBody Map<String,Object> tun und den JSON selbst dekodieren?

Danke!

+0

Es sollte nichts daran hindern, dies zu tun. Fehler 400 zeigt an, dass etwas mit der Anforderung oder dem Mapping falsch ist. Hat die 'User' Klasse einen Standard-NO-Arg-Konstruktor. –

+0

Der Wrapper ist ein absolut anderes Konzept in Java, was Sie ein paar Objekte haben, die Sie in der äußeren Klasse aggregieren möchten. –

+0

Welche Federversion verwenden Sie? –

Antwort

3

Ich werde meine eigene Frage beantworten. Ein besonderer Dank geht an Sotirios Delimanolis, weil er mir den Schlüssel gegeben hat, um zu untersuchen, was passiert ist.

Wie Sie wissen, erstelle ich die folgende json aus der Sicht:

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

ich es ein wenig verändert, weil ich erkennen, dass nicht notwendig ist, ein Objekt Abonnement und ein var Abonnement zu erstellen.Wenn Sie die JSON wie dieses bauen, wird es perfekt funktionieren:

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

Der Controller empfängt diese json:

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

Und die 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 ... Was ist das Problem? Ich habe einen Fehler 400 Falsche Anfrage erhalten ... Ich habe den MappingJackson2HttpMessageConverter wie Sotirios vorgeschlagen und es gab eine Ausnahme (Kein passender Konstruktor). Jackson Mapping kann keine innere Klasse erstellen, unabhängig davon, ob diese Klasse nicht statisch ist. SubscribeWrapper auf statisch zu setzen war die Lösung für mein Problem.

Sie können auch diese Antworten überprüfen: 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

Und wenn Sie Probleme haben, deserialisieren, überprüfen Sie dies: http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type

Danke für alle Antworten.

2

Sie müssen dies nicht selbst tun. Sie müssen diese Abhängigkeit in Ihrem Pom hinzufügen:

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

Danach wird Spring die Konvertierung für Sie tun.

+0

Ja, ich habe die Abhängigkeit. Es funktioniert, wenn ich nur den Benutzer sende, der einen Benutzernamen, ein Kennwort hat ... aber wenn ich versuche, das Subskriptionsobjekt zu senden, wird nicht zugeordnet. Ein Ansatz, falls der Subscription-Wrapper nicht funktioniert, ist ResponseBody String oder ResponseBody Map , und er selbst erledigt die Elemente und konvertiert sie in meine Objekte. – mannuk

+0

Ich habe kein Detail verstanden. Sie sagten, dass wenn Sie nur ein User-Objekt senden (senden Sie es an eine andere URL?), Es funktioniert, aber wenn Sie das ganze Abonnement senden, funktioniert das nicht. Ist das richtig? Wenn ja, versuchen Sie zuerst, die Mapping-URLs zu überprüfen, und den HTTP-Inhaltstyp, der für json angegeben wurde, zu überprüfen. – mvb13

+0

Könnten Sie näher erläutern, wie die Feder es macht? Ist die einzige Jackson-Integration ist es möglich, es in JSON-Format zu konvertieren. OP erwartet, das Modell mit dem @ ResponseBody zu füllen. –

10

Ein Blick auf Ihre JSON

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

Das Wurzelelement ist subscription und es ist ein JSON-Objekt. Ihre Subscription Klasse hat kein subscription Feld. Es gibt also nichts, um das Element subscription zuzuordnen, und es schlägt daher mit einer 400 Bad Request fehl.

Erstellen Sie eine Klasse SubscriptionWrapper

public class SubscriptionWrapper { 
    private Subscription subscription; 

    public Subscription getSubscription() { 
     return subscription; 
    } 

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

und Ihre Behandlungsmethode ändern, ein Argument dieser Art

public @ResponseBody SimpleMessage subscribeUser(@RequestBody SubscriptionWrapper subscriptionWrapper) 

Sie könnten annehmen müssen die ObjectMapper in MappingJacksonHttpMessageConverter (FYI konfigurieren, sollten Sie MappingJackso2nHttpMessageConverter verwenden), so dass fehlende Eigenschaften ignoriert werden.

+0

Würdest du gerne deine letzten Zeilen erklären? Die Konfiguration von ObjectMapper und MappingJackson2HttpMessageConverter. In meinem Fall haben die Objekte fehlende Eigenschaften, da sie nicht notwendig sind. – mannuk

+0

@mannuk 'MappingJackson2HttpMessageConverter' verwendet die neuen Jackson-Bibliotheken mit dem Paket' com.fasterxml.jackson'. 'ObjectMapper' hat eine' configure() 'Methode, mit der Sie Deserialisierungs- und Serialisierungsfunktionen konfigurieren können. Vielleicht möchten Sie sich einige davon ansehen. –

+0

Kennen Sie irgendeine Website, wo ich es überprüfen kann? Ich würde gerne mehr über den Konverter und die Konfigurationsmethode erfahren. Ich werde deine Antwort am Montag bei der Arbeit testen und dann kann ich dir meinen Fortschritt sagen – mannuk

Verwandte Themen