2015-06-30 12 views
5

abbiamo il nostro stato definito come:Scala json4s tratto sigillato come enumerazioni

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

Il nostro status assomiglia:

val status = Status.StatusA 

Esiste un modo per (de) serializzare che tipo di struttura con predefinita json4s fomratters?

Abbiamo provato con defult formattatore come:

implicit val formats = new org.json4s.DefaultFormats 

e non ha funzionato. Poi abbiamo cercato di utilizzare ext fornito da json4s con il supporto Enum:

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

e non ha funzionato di nuovo. Abbiamo dovuto cambiare totalmente la struttura dello sealed trait in effettivo Enumeration s. C'è un modo per farlo con case class es?

risposta

0

Ecco un esempio funzionante completo, ho modificato un po 'le classi per rendere l'esempio più semplice e in questo modo è possibile utilizzare il "nome" in diversi modi in cui si può effettivamente omettere il "nome def", ma in questo caso si sarà necessario modificare un po 'il serializzatore. Il secondo serializzatore è appena sotto.



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

ecco il secondo Serializzatore, utilizzando il secondo non è necessario per definire il codice in più nel vostro "enumerazioni"



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

Ed ecco come questo si guarda quando viene eseguito, JSON compatta :

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

abbastanza jSON:

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

Oggetto avanzato toString: SimpleRichObject (Ecco un'altra stringa, 1234, Elenco (StatoA, StatoB))

Problemi correlati