2014-09-23 32 views
1

消除我已經採取了看看關於這個話題的答案,但我一直沒有得到如何解決在這個片段中的問題:斯卡拉警告:抽象類型模式Z爲未選中,因爲它是由擦除

object MyObj { 

    def validate[Z](json: JsValue)(implicit rds: Reads[Z]): Either[Error,Z] = { 
    json.validate[Z].map{ 
     case r: Z => Right(r) // Type Erasure here.... 
    }.recoverTotal{ 
     e => Left(JsonParsingError(JsError.toFlatJson(e).toString)) 
    } 
    } 

} 

任何幫助?

+0

剛纔看了你提出的修改通知 - 我建議保持它作爲一個'讀'。您可以通過執行'readsEither.reads(json)'或'Json.fromJson'將它應用到'JsValue',然後您可以安全地對結果值使用'.get'來解包生成的'JsSuccess',因爲你知道'readsEither'已經恢復了所有可能的失敗。這有點冗長,但它更具慣用性和可組合性。如果您不想進入「Reads」路徑,我還添加了另一種可能更簡潔的方式直接進入「Either」。 – acjay 2014-09-24 01:58:54

回答

1

我覺得你真的要殺的那個錯誤是下降類型: Z。你已經知道這將是一個Z如果validate首先給你一個JsSuccess。否則,您將以recoverTotal結束。

我想你想:

object MyObj { 
    def validate[Z](json: JsValue)(implicit rds: Reads[Z]): Either[Error,Z] = { 
    json.validate[Z].map(Right _).recoverTotal{ e => 
     Left(JsonParsingError(JsError.toFlatJson(e).toString)) 
    } 
    } 
} 

雖然你可能真正想要的是:

implicit def readsEither[Z](implicit rds: Reads[Z]): Reads[Either[Error, Z]] = Reads { json => 
    rds.reads(json).map(Right(_)).recoverTotal { e => 
    JsSuccess(Left(JsonParsingError(JsError.toFlatJson(e).toString))) 
    } 
} 

後一個例子是不錯的,因爲它定義了一個Reads,其組成很好。

我還沒有測試任何這個,也不能真的,因爲我沒有JsonParsingError,但這應該或多或少地解決您的問題。

編輯:給你的代碼需要一個隱含Reads[Z]已經是事實,你也可以試試:

def jsonAsEither(json: JsValue)(implicit rds: Reads[Z]) = 
    Json.fromJson(json).asEither.left.map(/* ... */).e