2014-09-23 35 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