我有以下类型转换器:
import scala.concurrent.duration._
/**
* Type classes that define the message transformations to and fro between JSON and
* case class types
*/
object JsonMessageConversion {
implicit val resolveTimeout: Timeout = Timeout(3.seconds)
case class FailedMessageConversion(kafkaTopic: String, msg: String, msgType: String)
trait Converter[T <: KafkaMessage] {
def convertFromJson(msg: String): Either[FailedMessageConversion, T]
def convertToJson(msg: T): String
}
//Here is where we create implicit objects for each Message Type you wish to convert to/from JSON
object Converter {
val dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
implicit val jodaDateTimeReads: Reads[DateTime] = Reads[DateTime](js =>
js.validate[String].map[DateTime](dt =>
DateTime.parse(dt, DateTimeFormat.forPattern(dateFormat))
)
)
implicit val jodaDateTimeWrites: Writes[DateTime] = new Writes[DateTime] {
def writes(dt: DateTime): JsValue = JsString(dt.toString())
}
implicit object DefaultMessageConverter extends Converter[DefaultMessage] {
implicit val defaultMessageReads: Reads[DefaultMessage] = (
(__ \ "message").read[String] and
(__ \ "timestamp").read[DateTime](jodaDateTimeReads)
)(DefaultMessage.apply _)
implicit val defaultMessageWrites: Writes[DefaultMessage] = (
(__ \ "message").write[String] and
(__ \ "timestamp").write[DateTime](jodaDateTimeWrites)
)(unlift(DefaultMessage.unapply))
implicit val defaultMessageFormat: Format[DefaultMessage] =
Format(defaultMessageReads, defaultMessageWrites)
override def convertFromJson(msg: String): Either[FailedMessageConversion, DefaultMessage] = {
Json.parse(msg).validate[DefaultMessage] match {
case s: JsSuccess[DefaultMessage] => Right(s.value)
case _: JsError => Left(FailedMessageConversion("kafkaTopic", msg, "to: DefaultMessage"))
}
}
override def convertToJson(msg: DefaultMessage): String = {
Json.toJson(msg).toString()
}
}
implicit object DefaultMessageBundleConverter extends Converter[DefaultMessageBundle] {
implicit val defaultMessageReads = Converter.DefaultMessageConverter.defaultMessageReads
implicit val defaultMessageWrites = Converter.DefaultMessageConverter.defaultMessageWrites
implicit val defaultMessageBundleReads: Reads[DefaultMessageBundle] = (
(__ \ "messages").read[Seq[DefaultMessage]] and
(__ \ "timestamp").read[DateTime](jodaDateTimeReads)
)(DefaultMessageBundle.apply _)
implicit val defaultMessageBundleWrites: Writes[DefaultMessageBundle] = (
(__ \ "messages").write[Seq[DefaultMessage]] and
(__ \ "timestamp").write[DateTime](jodaDateTimeWrites)
)(unlift(DefaultMessageBundle.unapply))
implicit val defaultMessageFormat: Format[DefaultMessageBundle] =
Format(defaultMessageBundleReads, defaultMessageBundleWrites)
override def convertFromJson(msg: String): Either[FailedMessageConversion, DefaultMessageBundle] = {
Json.parse(msg).validate[DefaultMessageBundle] match {
case s: JsSuccess[DefaultMessageBundle] => Right(s.value)
case _: JsError => Left(FailedMessageConversion("kafkaTopic", msg, "to: DefaultMessageBundle"))
}
}
override def convertToJson(msg: DefaultMessageBundle): String = {
Json.toJson(msg).toString()
}
}
def apply[T: Converter] : Converter[T] = implicitly
}
}
编译时出错:
Error:(98, 16) type arguments [T] do not conform to trait Converter's type parameter bounds [T <: com.eon.pm.messages.KafkaMessage]
def apply[T: Converter] : Converter[T] = implicitly
如何摆脱这个错误?
答案 0 :(得分:1)
只需添加绑定到该方法的相同类型:
def apply[T <: KafkaMessage : Converter] : Converter[T] = implicitly
我不确定为什么编译器需要这种冗余,但这可以消除错误。