2016-06-24 1 views
0

Ich mag würde eine erweiterte Klasse in scala und ich einige Test-Code haben serialisiert ..Serialize erweiterte Klasse zu JSON in Scala mit Play-Framework Serializer

import org.specs2.mutable._ 
import org.specs2.runner._ 
import org.junit.runner._ 
import play.api.libs.json.Json 

@RunWith(classOf[JUnitRunner]) 
class JsonSerializerTest extends Specification { 

    class A(val s1: String) 
    case class B(s2: String) extends A("a") 

    "Application" should { 
    "serialize class to JSON" in { 
     implicit val bWrites = Json.writes[B] 
     implicit val bReads = Json.reads[B] 

     val bClass = B("b") 
     println(bClass.s1 + " " + bClass.s2) 

     val serialized = Json.toJson[B](bClass) 

     val s1 = (serialized \ "s1").asOpt[String] 

     s1 should beSome[String] 

    } 
    } 
} 

In diesem Fall Testdruck:

a b 
Application should 

'None' is not Some 
java.lang.Exception: 'None' is not Some 

Es bedeutet, dass s1-Feld von Elternklasse nicht serialisiert wurden.

Die Lösung

class A(val s1: String) 
case class B(override val s1: String, s2: String) extends A(s1) 

meist nicht akzeptabel, da in realen Anwendungsklassen haben viele Felder und explizit jedes Mal angeben, wenn ich verlängern Klasse den Code erschwert.

Gibt es eine andere Lösung für diesen Fall?

Antwort

0

Sie manuell die json Serializer erstellen können (hier beschrieben: https://www.playframework.com/documentation/2.5.x/ScalaJsonCombinators)

das Problem mit Ihrer Version ist, dass Json.writes und Json.reads sind Makros, die sich speziell an den Konstruktor der case class und den Aufbau der Serializer aus, dass suchen (Superklassenargumente werden nicht erfasst). Sie könnten Ihre eigene Version des Makro kopieren und rollen: https://github.com/playframework/playframework/blob/d6c2673d91d85fd37de424951ee5ad9f4f4cce98/framework/src/play-json/src/main/scala/play/api/libs/json/JsMacroImpl.scala

schließlich können Sie eine Funktion machen, die das Ergebnis von Json.writes und Json.reads, und fügt auf den gemeinsam genutzten Feldern nimmt Sie wollen. so etwas wie:

object A { 
    def writesSubclass[T](writer: Writes[T]): Writes[T] = new Writes[T] { 
    def writes(t: T) = Json.obj("s1" -> t.s1) ++ writer.writes(t).as[JsObject] 
    } 
} 

implicit val bWrites = A.writesSubclass(Json.writes[B]) 

je nachdem, wie oft Ihr A verlängert wird, könnte dies die beste Wahl sein.

Verwandte Themen