子类类型的隐式写入

时间:2015-09-21 13:32:01

标签: scala playframework playframework-2.0

我有一个Person类和Employee类。类Employee扩展了Person类。

我目前将类转换为JSON的隐式写法如下所示:

implicit val implicitPersonWrites = new Writes[Person] {
  def writes(v: Person): JsValue = {
    Json.obj("label" -> v.label, "age" -> v.age)
  }
}

implicit val implicitEmployeeWrites = new Writes[Employee] {
  def writes(v: Employee): JsValue = {
    Json.obj("label" -> v.label, "age" -> v.age, "company" -> v.company)
  }
}

问题是即使我的对象是Employee类型,也始终使用Person超类的隐式写入。因此,最后,输出中不存在特定于Employee类的字段。如何在继承的情况下正确地进行隐式写入?

1 个答案:

答案 0 :(得分:1)

三个选项:

  1. (在大多数情况下最好)使用合成而不是继承。而不是class Employee(...) extends Person(...))class Employee(person: Person, company: String)

  2. 如果你有一个固定的子类层次结构,那么,正如你在评论中提到的那样,调度implicitPersonWrites中的类型。这并不特别难看;这种情况一直发生在OptionList等。 Ideally you can turn Person into an algebraic data type.

  3. 使用您拥有的继承:

    implicit val implicitPersonWrites = new Writes[Person] {
      def writes(v: Person): JsValue = v.toJsValue
    }
    
    // no implicitEmployeeWrites 
    
    class Person(...) {
      def toJsValue = Json.obj("label" -> label, "age" -> age)
    }
    
    class Employee(...) extends Person(...) {
      override def toJsValue = Json.obj("label" -> label, "age" -> age, "company" -> company)
    }
    

    这有明显的缺点:

    1. Person和子类现在必须了解JsValue s;

    2. 这只能用于Writes之类的情况,其中type参数用作参数