uso tipos sirve serialización serializacion que para objetos interfaz funciona estructurados deserializacion datos cómo scala spray spray-json

scala - tipos - cómo serializar clases de casos con rasgos con jsonspray



tipos de serializacion (2)

Usted puede agregar un campo extra eq. type al serializar y utilícelo para determinar la implementación de rasgos al deserializar:

trait Animal case class Person(name: String) extends Animal case class Lion(age: Int) extends Animal implicit def personFormat = jsonFormat1(Person) implicit def lionFormat = jsonFormat1(Lion) implicit def animalFormat = new RootJsonFormat[Animal] { override def read(json: JsValue): Animal = json.asJsObject.fields.get("type") match { case Some(JsString("person")) => json.convertTo[Person] case Some(JsString("lion")) => json.convertTo[Lion] case t => deserializationError(s"Unable to deserialize Animal of type $t") } override def write(obj: Animal): JsValue = obj match { case e: Person => toJson(e, "person") case e: Lion => toJson(e, "lion") } def toJson[T](obj: T, objType: String)(implicit w: JsonWriter[T]): JsObject = { val o = obj.toJson.asJsObject o.copy(fields = o.fields + ("type" -> JsString(objType))) } }

Entiendo que si tengo:

case class Person(name: String)

Puedo usar

object PersonJsonImplicits extends DefaultJsonProtocol { implicit val impPerson = jsonFormat1(Person) }

y así serializarlo con:

import com.example.PersonJsonImplicits._ import spray.json._ new Person("somename").toJson

Sin embargo, ¿qué pasa si tengo

trait Animal case class Person(name: String) extends Animal

y tengo algun lugar en mi codigo

val animal = ???

y necesito serializarlo y quiero usar json spray

a qué serializador debería agregarle esperaba tener algo como:

object AnimalJsonImplicits extends DefaultJsonProtocol { implicit val impAnimal = jsonFormat???(Animal) }

donde tal vez necesitaba agregar algún emparejador para verificar de qué tipo es Animal, de modo que si fuera una persona lo dirigiría a una persona pero no encontraría nada ... estaba leyendo https://github.com/spray/spray-json y no entiendo como hacer eso ..

Entonces, ¿cómo puedo serializar el conjunto de

trait Animal case class Person(name: String) extends Animal

con json spray?


Usted tiene un par de opciones:

Opción 1

Extienda RootJsonFormat[Animal] y ponga su lógica personalizada para hacer coincidir diferentes tipos de Animal :

import spray.json._ import DefaultJsonProtocol._ trait Animal case class Person(name: String, kind: String = "person") extends Animal implicit val personFormat = jsonFormat2(Person.apply) implicit object AnimalJsonFormat extends RootJsonFormat[Animal] { def write(a: Animal) = a match { case p: Person => p.toJson } def read(value: JsValue) = // If you need to read, you will need something in the // JSON that will tell you which subclass to use value.asJsObject.fields("kind") match { case JsString("person") => value.convertTo[Person] } } val a: Animal = Person("Bob") val j = a.toJson val a2 = j.convertTo[Animal]

Si pega este código en el REPL de Scala, obtendrá esta salida:

a: Animal = Person(Bob,person) j: spray.json.JsValue = {"name":"Bob","kind":"person"} a2: Animal = Person(Bob,person)

Source

opcion 2

Otra opción es proporcionar jsonFormat s implícitos para Person y cualquier otra subclase de Animal y luego escribir su código de serialización de la siguiente manera:

def write(a: Animal) = a match { case p: Person => p.toJson case c: Cat => c.toJson case d: Dog => d.toJson }

Source