2016-07-20 16 views
0

ich eine Union-Typ wie folgt definiert:Implizite Parameter erforderlich

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) 
    } 
} 

Und dann schrieb ich, um einige Unit-Test zu überprüfen, ob ich serialisiert und eine CCWBiosChannel und NNBiosChannel deserialisieren. Ich habe versucht, eine Funktion unter einem generischen Typ T zu schreiben, weil ich die folgende Funktion wieder verwenden möchte:

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 
} 

ich einen Fehler bei der Zusammenstellung:

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) 

Die Sache, die ich nicht verstehen kann, ist, dass ich implizite Lese-/Schreibvorgänge für meine Fallklassen definiert habe. Außerdem müssen implicits Parameter nicht wie in meinem Fehler benötigt werden. Was stimmt also nicht mit meinem Code?

+0

Wie ca lling '.toJson' muss der' def serializeAndDeserializeBiosRecord' die Anforderung angeben, ein passendes 'Writes' zu haben. Übrigens wäre Ihr Def besser lesbar mit einer vollständigen Definition als mit Lambda. – cchantep

+0

Entschuldigung, ich habe den falschen Code eingegeben. Ich habe es aktualisiert. – alifirat

+0

Im impliziten Bereich des Aufrufers von 'serializeAndDeserialize' ist kein' Writes' verfügbar – cchantep

Antwort

1

Ich würde empfehlen, einen expliziten Typ auf implizite Einstellung liest und schreibt Definition wie folgt:

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) 
} 

Und dann ändern die Ihre serialize/deserialize Methode wie folgt aussehen:

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

Dann können Sie es auf folgende Art und Weise aufrufen (geben Sie die Typen entsprechend ein):

+0

Mit zwei generischen Typen kann das Ding funktionieren! Vielen Dank ! – alifirat

Verwandte Themen