2015-06-30 8 views
5

Wir haben unseren Status wie folgt definiert:Scala json4s versiegelten Zug als Aufzählungen

sealed trait Status 
case object Status { 
    case object StatusA extends Status 
    case object StatusB extends Status 
    case object StatusC extends Status 
} 

Unser Status wie folgt aussieht:

val status = Status.StatusA 

Gibt es eine Möglichkeit zu (de) Serialisierung diese Art von Struktur mit vordefinierten json4s fomratters?

Wir haben versucht, mit defult Formatierer wie:

implicit val formats = new org.json4s.DefaultFormats 

und es hat nicht funktioniert. Als nächstes haben wir versucht, ext von json4s mit Enum Unterstützung zu nutzen:

implicit val formats = org.json4s.DefaultFormats + new org.json4s.ext.EnumSerializer(Status) 

und es nicht wieder funktioniert hat. Wir mussten die Struktur der sealed trait vollständig zu tatsächlichen Enumeration s ändern. Gibt es eine Möglichkeit, es mit case class es zu tun?

Antwort

0

Hier ist ein voll funktionsfähiges Beispiel, ich habe Ihre Klassen ein wenig geändert, um das Beispiel einfacher zu machen und auf diese Weise können Sie den "Namen" auf verschiedene Arten verwenden, Sie können den "Def-Namen" tatsächlich weglassen, aber in diesem Fall Sie muss den Serialisierer etwas ändern. Der zweite Serializer befindet sich direkt darunter.



    sealed trait Status { 
     def name: String 
    } 

    case object Status { 
     def apply(name: String): Status = name match { 
     case StatusA.name => StatusA 
     case StatusB.name => StatusB 
     case StatusC.name => StatusC 
     case _ => throw new UnsupportedOperationException("Unknown value") 
     } 
    } 

    case object StatusA extends Status { 
     override val name = "StatusA" 
    } 

    case object StatusB extends Status { 
     override val name = "StatusB" 
    } 

    case object StatusC extends Status { 
     override val name = "StatusC" 
    } 

    class StatusSerializer extends CustomSerializer[Status](formats => 
     ({ 
     case JString(s) => Status(s) 
     case JNull => throw new UnsupportedOperationException("No status specified") 
     }, { 
     case status: Status => JString(status.name) 
     }) 
    ) 

    case class SimpleRichObject(someString: String, someInt: Int, statuses: List[Status]) 

    object Test extends App { 
     implicit val formats = DefaultFormats + new StatusSerializer 
     val obj = SimpleRichObject("Answer to life the universe and everything", 42, List(StatusA, StatusB, StatusC)) 

     def toCompactJsonString(any: Any) = { 
     JsonMethods.compact(JsonMethods.render(Extraction.decompose(any))) 
     } 

     def toPrettyJsonString(any: Any) = { 
     JsonMethods.pretty(JsonMethods.render(Extraction.decompose(any))) 
     } 

     /** To Json */ 
     println(s"Compact json:\n${toCompactJsonString(obj)}") 
     println(s"Pretty json:\n${toPrettyJsonString(obj)}") 

     /** From Json */ 
     val json = 
     """{ 
      | "someString":"Here is a another String", 
      | "someInt":1234, 
      | "statuses":["StatusA","StatusB"] 
      |}""".stripMargin 

     val richObj = JsonMethods.parse(json).extract[SimpleRichObject] 
     println(s"Rich object toString: $richObj") 
    } 

Hier ist der zweite Serializer, durch die zweite verwenden Sie keinen zusätzlichen Code in Ihren „Aufzählungen“



    class SecondStatusSerializer extends CustomSerializer[Status](formats => 
     ({ 
     case JString(s) => s match { 
      case "StatusA" => StatusA 
      case "StatusB" => StatusB 
      case "StatusC" => StatusC 
     } 
     case JNull => throw new UnsupportedOperationException("No status specified") 
     }, { 
     case status: Status => status match { 
      case StatusA => JString("StatusA") 
      case StatusB => JString("StatusB") 
      case StatusC => JString("StatusC") 
     } 
     }) 
    ) 

Und hier definieren müssen, wie dies bei der Ausführung, kompakte json sieht :

{"someString":"Answer to life the universe and everything","someInt":42,"statuses":["StatusA","StatusB","StatusC"]}

Ziemlich json:

{ 
    "someString":"Answer to life the universe and everything", 
    "someInt":42, 
    "statuses":["StatusA","StatusB","StatusC"] 
}

Rich-Objekt toString: SimpleRichObject (Hier ist ein weiterer String, 1234, Liste (StatusA, StatusB))