Binding JSON-nested Grails-Domain-Objekten
Ich bin die Entwicklung einer RESTful Schnittstelle, die verwendet wird, um JSON-Daten für eine JavaScript-Anwendung.
Auf der server-Seite, die ich verwenden Grails 1.3.7 und verwenden GORM Domain-Objekte für die Persistenz. Ich habe implementiert eine benutzerdefinierte JSON-Marshaller Unterstützung marshalling der geschachtelten Domänen-Objekte
Hier sind Beispiele für domain-Objekte:
class SampleDomain {
static mapping = { nest2 cascade: 'all' }
String someString
SampleDomainNested nest2
}
und
class SampleDomainNested {
String someField
}
Den SampleDomain Ressource ist veröffentlicht unter der URL /rs/sample/so /rs/sample/1 Punkte der SampleDomain Objekt mit der ID 1
Wenn ich render die Ressource mit meiner benutzerdefinierte json-marshaller (GET on /rs/Probe/1) bekomme ich folgende Daten:
{
"someString" : "somevalue1",
"nest2" : {
"someField" : "someothervalue"
}
}
das ist genau das, was ich will.
Nun kommt das problem: ich versuche zum senden der gleichen Daten an die Ressource /rs/sample/1 über STELLEN.
Binden Sie die json-Daten zum Domain-Objekt, das controller-handling die Anfrage fordert def domain = SampleDomain.get(id)
und domain.properties = data
wo die Daten der unmarshallt Objekt.
Wird die Bindung für die "classextender" - Feld funktioniert nur gut, aber das verschachtelte Objekt ist nicht gefüllt, mit dem verschachtelten Daten, so bekomme ich eine Fehlermeldung, dass die Eigenschaft "nest2" ist null, was nicht zulässig ist.
Ich habe bereits versucht, die Implementierung einer benutzerdefinierten PropertyEditorSupport
sowie eine StructuredPropertyEditor
und registrieren Sie den editor für die Klasse.
Seltsam, der editor wird nur aufgerufen, wenn ich die Lieferung nicht-geschachtelte Werte. Also, wenn ich senden Sie die folgenden an den server über PUT (das macht keinen Sinn 😉 )
{
"someString" : "somevalue1",
"nest2" : "test"
}
mindestens der property editor aufgerufen wird.
Ich schaute auf den code der GrailsDataBinder
. Ich fand heraus, dass die Einstellung der Eigenschaften einer Assoziation scheint zu funktionieren, indem Sie den Pfad des Verbandes anstelle der Bereitstellung einer Karte, so dass die folgenden Werke als gut:
{
"someString" : "somevalue1",
"nest2.somefield" : "someothervalue"
}
aber das hilft mir nicht, da ich nicht möchten, implementieren Sie ein benutzerdefiniertes JavaScript, JSON Objekt-Serialisierung.
Ist es möglich, Grails Datenbindung mithilfe von verschachtelten maps? Oder muss ich wirklich hieven zu implementieren, die von hand für jede domain-Klasse?
Vielen Dank,
Martin
- Sie haben eine benutzerdefinierte json-unmarshaller wie gut?
- Nein, ich habe keine benutzerdefinierte json-unmarshaller. Ich parse die Anfrage mittels Anfrage.JSON. Was ich möchte ist, einen property-editor, der das unterstützt sowohl das erstellen einer Domänen-Objekt aus einer Karte sowie das laden/die Zuordnung eines domain-Objekt-ID.
- Haben Sie versuchen, dieses plugin : grails.org/plugin/json-rest-api
- Danke für den Hinweis. Ich habe versucht, das plugin, aber es unterstützt nur "flach" domain-Objekte, dh alle assocations gerendert werden als IDs. Aber ich fand inspiration in das plugin. Ich denke ich werde mir zur Umsetzung ein mapper, deren Verhalten gesteuert wird von ein paar statics in die domain-Objekte (z.B. Ressource-url referenzierten Eigenschaften, embedded-Eigenschaften...)
- haben Sie versucht, gson ? Sie werden wahrscheinlich besser mit... aber ich bin sicher, es gibt einen Weg, um diesem die grails Weg.
- Ich habe auf der Suche in das tun dieses mit Gson und es ist sehr leicht bis zu einem Punkt. Das problem kommt, wenn in dem Fall, wo eine id-Eigenschaft vorhanden ist, die Sie Lesen möchten die domain-Instanz aus der Datenbank, anstatt nur den Bau einer neuen. Ich habe nicht herausgefunden, eine Möglichkeit, einen Blick Voraus in das JSON-stream zu sehen, wenn Sie eine id ohne auch re-implementieren Sie die Ruhe der Immobilie verbindlich Logik.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Da diese Frage wurde von Ihnen positiv bewertet werden mehrmals ich würde gerne teilen, was ich Tat, am Ende:
Da ich noch ein paar mehr Anforderungen umgesetzt werden wie Sicherheits-etc. Ich habe implementiert eine service-Schicht verbirgt die domain-Objekte aus dem Controller. Ich führte eine "dynamische DTO-Schicht", was übersetzt Domain-Objekte an Groovy Maps, die serialisiert werden kann ganz einfach über die standard-serialisierungsprogramme und die Implementierung des updates manuell. Alle semi-automatische/meta-Programmierung/command-Muster/... - basierte Lösungen, die ich versucht umzusetzen, scheiterte an einem gewissen Punkt, meist resultierend in fremden GORM Fehler oder eine Menge von Konfigurations-code (und viel Frust). Die update-und Serialisierungs-Methoden für die DTOs sind Recht unkompliziert und umgesetzt werden könnte, sehr schnell. Es nicht vorstellen eine Menge doppelten code als gut, da müssen Sie angeben, wie die domain-Objekte werden serialisiert, wenn man eh nicht veröffentlichen wollen, um Ihre internen Domänen-Objekt-Struktur. Vielleicht ist es nicht die eleganteste Lösung, aber es war die einzige Lösung, die wirklich für mich gearbeitet. Es erlaubt mir auch zu implementieren, batch-updates, da die update-Logik ist nicht mit dem http-Anforderungen nicht mehr.
Aber ich muss sagen, dass ich nicht glaube, dass grails ist die entsprechende tech-stack am besten geeignet für diese Art von Anwendung, denn es macht Ihre Anwendung sehr schweres und inflexbile. Meine Erfahrung ist, dass sobald Sie anfangen, Dinge zu tun, die nicht unterstützt werden vom framework standardmäßig, es beginnt immer chaotisch. Außerdem glaube ich nicht, wie die Tatsache, dass der "repository" - Ebene in grails im wesentlichen existiert nur als Teil der domain-Objekte eingeführt, die eine Menge Probleme und führte mehrere "proxy services" emuliert eine repository-Schicht. Wenn Sie beginnen das erstellen einer Anwendung mithilfe einer json-rest-Schnittstelle, würde ich vorschlagen, sich entweder für eine sehr leichte Technologie wie node.js oder, wenn Sie wollen/müssen-stick auf einem java-stack basiert, verwenden Sie ein standard-framework spring + spring mvc + spring-Daten mit einer schönen und sauberen dto-Schicht (das ist, was ich habe migriert und es funktioniert wie ein Charme). Sie müssen nicht zu schreiben, eine Menge boilerplate-code, und Sie sind völlig in Kontrolle über das, was tatsächlich geschieht. Außerdem bekommen Sie bei uns starke Typisierung erhöht die Produktivität der Entwickler sowie die Wartbarkeit und das legitimiert die zusätzliche LOCs. Und natürlich starke Typisierung bedeutet, dass starke Werkzeuge!
Ich angefangen zu schreiben, einen blog-Eintrag beschreibt die Architektur kam ich mit (mit einem Beispiel-Projekt natürlich), aber ich habe nicht viel Zeit jetzt, es zu beenden. Wenn es fertig ist werde ich den link, um es hier zur Referenz.
Hoffe, das kann als inspiration dienen für Leute mit ähnlichen Problemen.
Prost!
Es erfordert, dass Sie die Klasse name:
Ich weiß, es erfordert andere Eingabe, die Ausgabe, die es produziert.
Wie ich bereits im Kommentar erwähnt, könnten Sie besser dran, unter Verwendung der gson-Bibliothek.
Nicht sicher, warum Sie schrieb Ihre eigene json-marshaller, mit xstream herum.
Sehen http://x-stream.github.io/json-tutorial.html
Wir waren sehr zufrieden mit xstream für unsere back-end (grails-basierten) services und auf diese Weise können Sie die render-marshall, die in xml oder json, oder überschreiben Sie die Standard-Anordnung für ein bestimmtes Objekt, wenn Sie mögen.
Über Bord werfen scheint, um mehr zu produzieren kompakte weniger lesbaren JSON und Sie können führen Sie in eine Bibliothek Kollision Material, aber die Standard-interne json-stream-renderer ist anständig.
Wenn Sie den service veröffentlichen, um die öffentlichkeit, Sie wollen die Zeit nehmen, um die Rückkehr entsprechenden HTTP-Protokoll-Antworten für Fehler etc... ($.02)