我正在为我的 Java 类创建 Reads
和 Writes
以利用 Play Framework 的 JSON 库。
我的一个类(class)有一个抽象类(class)字段。
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}
但是下一步,创建一个 Reads[AbstractObj]
,对我来说没有意义,因为抽象类不能被实例化。
我想 Writes[AbstractObj]
应该是这样的:
implicit val AbstractObjWrites: Writes[AbstractObj] =
(JsPath \ "otherField").write[String].contramap{x: AbstractObj => x.getOtherField}
但是 Reads[AbstractObj]
呢?
最佳答案
由于具体类型在运行时才可用,因此您必须在运行时键入检查/解析类型。您可以使用函数式语法 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")
}
}
}
通过这种方式,您仍然可以为具体类型创建可重复使用的格式/读取/写入,您可以在编译时确实知道您正在序列化/反序列化哪种对象的地方使用这些类型。
关于java - 为抽象类创建 Read[T] 和 Write[T],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21718075/