【问题标题】:Creating Read[T] and Write[T] for Abstract Class为抽象类创建 Read[T] 和 Write[T]
【发布时间】:2014-03-10 04:43:10
【问题描述】:

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

我的一个类有一个abstract类字段。

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] 呢?

【问题讨论】:

  • 这对我来说也没有意义......
  • 意思是我的问题?或答案? :)

标签: java json scala playframework


【解决方案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") 
    }
  }
}

通过这种方式,您仍然可以为具体类型创建可重用的格式/读取/写入,您可以在编译时确实知道您正在序列化/反序列化哪种对象的情况下使用这些类型。

【讨论】:

    【解决方案2】:

    由于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 
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-12
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多