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

标签 java json scala playframework

我正在为我的 Java 类创建 ReadsWrites 以利用 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/

相关文章:

java - 使用 xuggler 设置 mp3 比特率

javascript - 尝试使用 angularJS 从 JSON 中查找特定对象,并使用 .find() 从 lodash 中查找特定对象

java - 不使用外部库读取 JSON 文件(仅使用 org.json 更新)

scala - 带有来自 shell 的 CLI 参数的“sbt run”

scala - 您如何使用 Scala 将功能混合到迭代过程的每个步骤中?

java - mutator 方法可以应用于 ArrayList 中的对象吗?

java - 如何访问正在运行的线程/runnable?

java - Exoplayer 不显示字幕

scala - 使用Spark CSV软件包读取非常大的文件时出错

java - 在 Java 中重新格式化 JSON 数组的最有效内存方式