2016-11-22 1 views
3

Ich komme aus einem Java-Hintergrund, wo Mapping POJOs wirklich, wirklich einfach ist. Ich erwarte, dass das Gleiche für scala/play gilt (und zwar für Fallklassen), aber die Dinge scheinen wirklich die Blätter zu beschmutzen, wenn ich versuche, ein bisschen Hierarchie hinzuzufügen.Scala play JSON Mapping funktioniert nicht mit Vererbung

Also, mein spezifisches Problem ist, dass ich versuche, verschiedene Nachrichten über einen Websocket zu senden und JSON ist einfach nur gut dafür. Aber ich möchte nicht für jede Art von Nachricht gemeinsame Attribute in jeder Klasse wiederholen, daher die Vererbung.

Also versuche ich, etwas wie folgt aus:

class WSMessage(messageType:String) 
class EventMessage(eventType:String) extends WSMessage("event") 
class AlertMessage(alertType:String) extends WSMessage("alert") 

und es können weitere Spezifität sein ....

class LoginEventMessage(login:Login) extends EventMessage("login") 
class OrderEventMessage(order:Order) extends EventMessage("order") 
class TerrainAlertMessage(terrain:Terrain) extends AlertMessage("terrain") 

sei nun angenommen, ich so etwas gesetzt haben:

object LoginEventMessage { implicit val fmt = Json.format[LoginEventMessage] } 

UND

object Login { implicit val fmt = Json.format[Login] } 

auf jedes Objekt in jedem Schritt der Hierarchie (was wirklich nervig ist) Ich bekomme immer noch nur die niedrigste Ebene Attribute in JSON konvertiert.

Zum Beispiel

Json.toJson(new LoginEventMessage(theLogin)) 

liefert so etwas wie

{ "login": { "username": "foo", "timestamp": "0000000" } } 

statt

{ "messageType": "event", "eventType": "login", "login": { "username": "foo", "timestamp": "0000000" } } 

Jede Anleitung, wie dies zu tun, ohne alle Attribute auf der untersten Ebene zu wiederholen wäre willkommen !

Prost.

Editiert, um Versuch # 2 hinzuzufügen Ich versuchte, die Dinge ein bisschen basierend auf Zoltáns Kommentar zu modifizieren. Hier ist das Ergebnis:

object Login { implicit val fmt = Json.format[Login] } 
case class Login(username:String, timestamp:DateTime) 

object WSMessage { implicit val fmt = Json.format[WSMessage] } 
class WSMessage(val messageType:String) 
object EventMessage { implicit val fmt = Json.format[EventMessage] } 
class EventMessage(val eventType:String) extends WSMessage("event") 
object LoginEventMessage { implicit val fmt = Json.format[LoginEventMessage] } 
class LoginEventMessage(val login:Login) extends EventMessage("login") 

Wir bekommen Kompilierungsfehler, weil dies keine Fallklassen sind (sie mögen keine Vererbung).

[error] /app/model/dto/WSMessage.scala:15: No unapply or unapplySeq function found 
[error] object WSMessage { implicit val fmt = Json.format[WSMessage] } 
[error]            ^
[error] /app/model/dto/WSMessage.scala:17: No unapply or unapplySeq function found 
[error] object EventMessage { implicit val fmt = Json.format[EventMessage] } 
[error]             ^
[error] /app/model/dto/WSMessage.scala:19: No unapply or unapplySeq function found 
[error] object LoginEventMessage { implicit val fmt = Json.format[LoginEventMessage] } 
[error]              ^
[error] three errors found 
[error] (compile:compileIncremental) Compilation failed 
[error] application - 

Antwort

1

Denken Sie daran, dass, wenn Klassen deklariert, Klassen Fall im Gegensatz alle Parameter des Konstruktors protected Felder sind mit val erklärt, es sei denn.

Also, um alle Felder der JSON Formatierer zu belichten, müssen Sie sie mit val erklären:

class WSMessage(val messageType:String) 
class EventMessage(val eventType:String) extends WSMessage("event") 
class AlertMessage(val alertType:String) extends WSMessage("alert") 

class LoginEventMessage(val login:Login) extends EventMessage("login") 
class OrderEventMessage(val order:Order) extends EventMessage("order") 
class TerrainAlertMessage(val terrain:Terrain) extends AlertMessage("terrain") 
+0

Ich glaube, dass ich diesen Ansatz versucht, so gut, ich werde erneut testen und meine Erkenntnisse berichten. –

Verwandte Themen