本文介绍了播放json写入子类会给出模棱两可的隐式值错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用play框架,并且有一个抽象类:

I'm using the play framework, and have an abstract class:

 abstract class Base{...}

在随播对象中有自己的隐式JSON编写器

which has its own implicit JSON writer within the companion object

object Base {
   implicit val baseWrites: Writes[Base] = (...)(unlift(Base.unapply))
}

我将这个抽象类子类化:

I subclass this abstract class:

case class SubClass{...}

在其伴随对象中也有自己的隐式JSON编写器

which also has its own implicit JSON writer within its companion object

object SubClass {
   implicit val subClassWrites: Writes[SubClass] = (...)(unlift(SubClass.unapply))
}

当我尝试使用Json.toJson(SubClass)序列化子类对象时,出现错误:

When I try to serialize the subclass object using Json.toJson(SubClass), I get an error:

[error]  both value subClassWrites in object SubClass of type => play.api.libs.json.
Writes[models.SubClass]
[error]  and value baseWrites in object Base of type =>        
play.api.libs.json.Writes[models.Base]
[error]  match expected type play.api.libs.json.Writes[models.SubClass]
[error]  Ok(Json.toJson(SubClass.find(id)))

有什么方法可以消除歧义?

Is there any way to remove the ambiguity?

推荐答案

由于Writes具有变量类型参数A:

You are getting a collision because Writes has a contravariant type parameter A:

trait Writes[-A] extends AnyRef

这意味着Writes[Base]Writes[SubClass]的子类-您可以在需要Writes[SubClass]的地方使用Writes[Base].

It means that Writes[Base] is subclass of Writes[SubClass] - you can use Writes[Base] where Writes[SubClass] is required.

问题在这里:

val base: Base = new SubClass(...)
val jsBase = Json.toJson(base)

因此,Writes[Base]应该能够序列化SubClass的实例.在这种情况下,您可以使用ADT:

So Writes[Base] should be able to serialize an instance of SubClass. You could use ADT in this case:

sealed trait Base
object Base {
  implicit val baseWrites: Writes[Base] = 
    new Writes[Base]{
      def writes(o: Base): JsValue = o match {
        case s: SubClass => SubClass.writes.writes(s)
        case s: SubClass2 => SubClass2.writes.writes(s)
      }
    }
}

case class SubClass(...) extends Base
object SubClass {
  val writes: Writes[SubClass] = (...)(unlift(SubClass.unapply))
}

case class SubClass2(...) extends Base
object SubClass2 {
  val writes: Writes[SubClass2] = (...)(unlift(SubClass2.unapply))
}

使用sealed关键字,如果match不够详尽,则会收到警告.

With sealed keyword you'll get a warning in case match is not exhaustive.

这篇关于播放json写入子类会给出模棱两可的隐式值错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 16:13