【问题标题】:Play Scala JSON Writes & Inheritance播放 Scala JSON 写入和继承
【发布时间】:2016-08-29 15:53:34
【问题描述】:

//Item.scala

package model
trait Item {val id: String}

class MItem(override val id: String, val name: String) extends Item

class DItem(override val id: String, override val name: String, val name2: String)
  extends MItem(valid, name, name2)

object ItemWrites {

  implicit  val MItemWrites = new Writes[MItem] {
    def writes(dItem: MItem) = Json.obj(
      "id" -> mItem.id,
      "name" -> mItem.name
    )
  }

  implicit  val DItemWrites = new Writes[DItem] {
    def writes(dItem: DItem) = Json.obj(
      "id" -> dItem.id,
      "name" -> dItem.name,
      "name2" -> dItem.name2
    )
  }

}

//Response.scala

package model
import ItemWrites.MItemWrites
import ItemWRites.DItemWrites

trait Response {
  val title : String,
  val items : Seq[Item],
}

case class MResponse(title: String, items: Seq[MItem]) extends Response

case class DResponse(title: String, items: Seq[DItem]) extends Response

object ResponseWrites  {

  implicit val mResponseWrite = new Writes[MResponse] {

    def writes(mResponse: MResponse) = Json.obj(
      "title" -> mResponse.title,
      "items" -> mResponse.items
    )
  }

  implicit val dResponseWrite = new Writes[DResponse] {

    def writes(dResponse: DResponse) = Json.obj(
      "title" -> dResponse.title,
      "items" -> dResponse.items // **compile time error**
    )
  }

}

我在 dResponse.items 行出现编译时错误。

> [error]  Note: implicit value dtcTopicPageResponseWrite is not
> applicable here because it comes after the application point and it
> lacks an explicit result type
> [error] "items" -> dResponse.items

似乎发生这种情况是因为 DItem 继承了 MItem 形式,并且编译在子类和超类之间变得混乱。我该如何解决这个问题。

【问题讨论】:

    标签: json scala inheritance playframework


    【解决方案1】:

    通过明确说明您在 ItemWrites 中声明的 Writes 的类型,我能够在 Scala 2.11、Play 2.5.x 中编译您的代码 - 即:

    object ItemWrites {
    
      implicit val MItemWrites:Writes[MItem] = new Writes[MItem] {
        def writes(mItem: MItem) = Json.obj(
          "id" -> mItem.id,
          "name" -> mItem.name
        )
      }
    
      implicit val DItemWrites:Writes[DItem] = new Writes[DItem] {
        def writes(dItem: DItem) = Json.obj(
          "id" -> dItem.id,
          "name" -> dItem.name,
          "name2" -> dItem.name2
        )
      }
    }
    

    一旦我这样做了,Scala 就能够找出哪个隐式是正确的。

    【讨论】:

    • 你说得对,编译错误消失了,但在运行时,当我执行 Json.toJson(anyResponse.asInstanceOf[DResponse]) cc @millhouse 时,DResponse 仍然呈现 MItem 而不是 DItem
    • 1.应始终指明实例类型类的预期类型(例如Writes)。 2.你不应该这样玩cast:编译器正确解析Write[DItem],为DResponse.items: Seq[DItem]
    【解决方案2】:

    您应该明确设置要使用的 Writer[T],因为它们使用继承。我没有测试下面的代码,但它应该可以编译和工作;

    implicit val dResponseWrite = new Writes[DResponse] {
    
        import ItemWrites.DItemWrites
    
        def writes(dResponse: DResponse) = Json.obj(
          "title" -> dResponse.title,
          "items" -> Json.toJson(dResponse.items) // **compile time error**
        )
      }
    

    【讨论】:

      【解决方案3】:

      我认为对你来说最好有一个超类型 Item 的 Writes,它只会匹配大小写以检查它的类型并执行 toJson。不要忘记隐式导入它

      object ItemWrites {
      
        implicit  val MItemWrites = new Writes[MItem] {
          def writes(dItem: MItem) = Json.obj(
            "id" -> mItem.id,
            "name" -> mItem.name
          )
        }
      
        implicit  val DItemWrites = new Writes[DItem] {
          def writes(dItem: DItem) = Json.obj(
            "id" -> dItem.id,
            "name" -> dItem.name,
            "name2" -> dItem.name2
          )
        }
      
        implicit  val ItemWrites = new Writes[Item] {
          def writes(item: Item) = item match {
           case i: DItem => i.toJson //code for converting DItem to Json
           case i: MItem => i.toJson //code to convert MItem to Json
           case _ => throws new RuntimeException("Unsupported Type.")
         }
        }
      }
      

      【讨论】:

      • 我得到这种方法的模糊隐含值编译器错误:(
      猜你喜欢
      • 1970-01-01
      • 2021-03-07
      • 2020-11-11
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2013-07-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多