Java 为抽象类创建读[T]和写[T]

Java 为抽象类创建读[T]和写[T],java,json,scala,playframework,Java,Json,Scala,Playframework,我正在为我的Java类创建读取和写入,以利用Play框架的JSON库 我的一个类有一个抽象类字段 ConcreteObj.java public class ConcreteObj { private AbstractObj someField; public ConcreteObj(AbstractObj someField) { this.someField = someField; } public AbstractObj getSomeField() { return thi

我正在为我的Java类创建
读取
写入
,以利用Play框架的JSON库

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

ConcreteObj.java

public class ConcreteObj {

private AbstractObj someField;

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

public AbstractObj getSomeField() { return this.someField };

读写

  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}
然而,下一步,创建一个
读取[AbstractObj]
,对我来说没有意义,因为抽象类无法实例化

我假设
写入[AbstractObj]
的代码如下所示:

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

但是
读[AbstractObj]

呢,因为具体类型在运行时之前不可用,所以您必须在运行时键入check/parse type。您可以使用函数语法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") 
    }
  }
}

通过这种方式,您仍然可以为具体类型创建可重用的格式/读/写,您可以在编译时知道要序列化/反序列化什么类型的对象时使用这些格式。

因为
ConcreteObj
的实现将与
AbstractObj
的任何实现一起工作,我想您可以这样做这:

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

// I don't know the structure of AbstractObj, but this should give you an idea
implicit val AbstractObjReads: Reads[AbstractObj] = 
  (JsPath \ "field").read[String].map{ s: String => 
    new AbstractObject { 
      val field = s 
    }
  }

这对我来说也没有意义…是指我的问题吗?或者答案是什么?:)