需要隐式参数

时间:2016-07-20 12:55:15

标签: scala

我定义了一个这样的联合类型:

import play.api.libs.json._
import reactivemongo.play.json._
import reactivemongo.play.json.collection.JSONCollection
import play.api.libs.json.Reads._
import play.api.libs.functional.syntax._

object Models {

sealed trait BiosChannel {
    val id : Int
    val label : String
    val samplingRate : Int
    val scaleFactor : Double
  }

case class CCWBiosChannel
    (
      id : Int,
      label : String,
      samplingRate : Int,
      scaleFactor : Double
    ) extends BiosChannel



case class NNBiosChannel
    (
      id : Int,
      label : String,
      samplingRate : Int,
      scaleFactor : Double,
      amplitude : Double,
      position : Option[String],
      localisation : Option[List[Double]]
    ) extends BiosChannel

  implicit val biosChannelReads = {
    val ccwBiosChannel = Json.reads[CCWBiosChannel]
    val nnBiosChannel = Json.reads[NNBiosChannel]
    __.read[CCWBiosChannel](ccwBiosChannel).map(x => x : BiosChannel) |
    __.read[NNBiosChannel](nnBiosChannel).map(x => x : BiosChannel)
  }

  implicit val biosChannelWrites = Writes[BiosChannel] {
    case ccwBiosChannel : CCWBiosChannel =>
      Json.writes[CCWBiosChannel].writes(ccwBiosChannel)
    case nnBiosChannel : NNBiosChannel =>
      Json.writes[NNBiosChannel].writes(nnBiosChannel)
  }
}

然后,我编写了一些单元测试,以检查是否可以序列化和反序列化CCWBiosChannel和NNBiosChannel。我尝试编写一个采用泛型类型T的函数,因为我想重用以下函数:

import org.scalatest._
import play.api.libs.json._
import BiosModels._

class BiosModelsSpec extends FlatSpec with Matchers {  

def serializeAndDeserialize[T](implicit reads : Reads[T], writes : Writes[T]) =
    ((x : T) => Json.toJson(x)) andThen ((y) => y.validate[BiosRecord].get)
val ccwBiosChannels = List(CCWBiosChannel(0, "",-1,0.0, ChannelType.ECG, Units.mV, blocks))
val ccwBiosEvents = List(CCWBiosEvent(0L,0L,Some(""), CCWEventType.NOTWORN, CCWEventSource.mELEC))
val ccwBiosRecord = CCWBiosRecord("", "", 0L, 0L,1, ccwBiosChannels, Some(ccwBiosEvents))

 serializeAndDeserialize(ccwBiosChannel) // compilation error here
}

我在编译中遇到一个错误:

not enough arguments for method serializeAndDeserialize: (implicit reads: play.api.libs.json.Reads[T], implicit writes: play.api.libs.json.Writes[T])T => com.bioserenity.core.data.BiosModels.BiosRecord.
[error] Unspecified value parameter writes.
[error]     serializeAndDeserialize(ccwBiosChannel)

我无法理解的是我为我的case类定义了隐式读/写。此外,必须不要像我的错误那样需要implicits参数。那么我的代码有什么问题呢?

1 个答案:

答案 0 :(得分:1)

我建议在隐式读写定义上设置一个显式类型,如下所示:

implicit val biosChannelReads: Reads[BiosChannel] = {
  val ccwBiosChannel = Json.reads[CCWBiosChannel]
  val nnBiosChannel = Json.reads[NNBiosChannel]
  __.read[CCWBiosChannel](ccwBiosChannel).map(x => x : BiosChannel) |
    __.read[NNBiosChannel](nnBiosChannel).map(x => x : BiosChannel)
}

implicit val biosChannelWrites: Writes[BiosChannel] = Writes[BiosChannel] {
  case ccwBiosChannel : CCWBiosChannel =>
    Json.writes[CCWBiosChannel].writes(ccwBiosChannel)
  case nnBiosChannel : NNBiosChannel =>
    Json.writes[NNBiosChannel].writes(nnBiosChannel)
}

然后修改serialize / deserialize方法,如下所示:

def serializeAndDeserialize[T, V](x: T)(implicit reads : Reads[V], writes : Writes[T]): V = {
  Json.toJson(x).validate[V].get
}

然后您可以通过以下方式调用它(根据需要填写类型):

serializeAndDeserialize[List[<input type here>], List[<output type here>]](ccwBiosChannels)