为抽象类创建Read [T]和Write [T]

Kev*_*ith 6 java json scala playframework

我正在为Java类创建ReadsWrites使用Play Framework的JSON库.

我的一个类有一个抽象类字段.

ConcreteObj.java

public class ConcreteObj {

private AbstractObj someField;

public ConcreteObj(AbstractObj someField) {
   this.someField = someField;
}

public AbstractObj getSomeField() { return this.someField };
Run Code Online (Sandbox Code Playgroud)

...

读写

  implicit val ConcreteObjReads: Reads[ConcreteObj] =
    (JsPath \ "someField").read[AbstractObj].map{x: AbstractObj => new ConcreteObj(x)}

  implicit val ConcreteObjWrites: Writes[ConcreteObj] =
    (JsPath \ "someField").write[AbstractObj].contramap{x: ConcreteObj => x.getField}
Run Code Online (Sandbox Code Playgroud)

然而,下一步,创建一个Reads[AbstractObj],对我来说没有意义,因为抽象类无法实例化.

我想这Writes[AbstractObj]看起来像:

implicit val AbstractObjWrites: Writes[AbstractObj] = 
   (JsPath \ "otherField").write[String].contramap{x: AbstractObj => x.getOtherField}
Run Code Online (Sandbox Code Playgroud)

但是Reads[AbstractObj]呢?

joh*_*ren 1

由于具体类型直到运行时才可用,因此您必须在运行时键入检查/解析类型。您可以使用函数语法 api 来完成此操作,但我已经在这些情况下实际实现了读取/写入/格式,大致如下:

implicit object Example extends Reads[AbstractThing] {

  def reads(json: JsValue) = {
    // somehow figure out the concrete subclass of AbstractThing
    // based on the json
    (json \ "type").as[String] match {
      case "type1" => Json.fromJson[Concrete1](json)
      case "type2" => Json.fromJson[Concrete2](json)
      case t => JsError(s"Unknown concrete type of AbstractThing: $t") 
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这样,您仍然可以为具体类型创建可重用的格式/读取/写入,您可以在编译时知道要序列化/反序列化的对象类型的情况下使用这些格式