Scala 提取部分应用函数中的隐式转换异常
我有一个使用宏构造的case类copy方法的映射,使用隐式转换将输入转换为正确类型的copy方法,称为JsValue是Play Framework json值Scala 提取部分应用函数中的隐式转换异常,scala,implicit-conversion,implicit,Scala,Implicit Conversion,Implicit,我有一个使用宏构造的case类copy方法的映射,使用隐式转换将输入转换为正确类型的copy方法,称为JsValue是Play Framework json值 case class Clazz(int: Int, string: String) implicit def jsonToInt(json: JsValue): Int = json.as[Int] implicit def jsonToStr(json: JsValue): String = json.as[String] val
case class Clazz(int: Int, string: String)
implicit def jsonToInt(json: JsValue): Int = json.as[Int]
implicit def jsonToStr(json: JsValue): String = json.as[String]
val copyMap: Map[String, (Clazz, JsValue) => Clazz] =
Map("int" -> (c: Clazz, json: JsValue) => c.copy(int = json),
"string" -> (c: Clazz, json: JsValue) => c.copy(string = json))
我想对从copyMap检索到的函数部分应用一个输入,例如
在这种情况下,当尝试在完全应用函数时将JsStringnon_int_输入转换为int时,函数将引发异常,但我希望在部分应用JsValue输入时出现此错误-完全应用函数涉及从数据库检索Clazz实例,所以如果字符串输入无效,我宁愿抢占它
是否有一种方法可以触发/提取部分应用函数中的任何隐式转换错误?我想我可能已经找到了解决方案
case class Clazz(int: Int, string: String)
implicit def jsonToInt(json: JsValue) = json.as[Int]
implicit def jsonToStr(json: JsValue) = json.as[String]
val copyMap[String, (JsValue) => Try[(Clazz) => Clazz]] =
Map(
"int" -> {
(json: JsValue) => Try[(Clazz) => Clazz] =
Try {
val i: Int = json
(c: Clazz) => c.copy(int = i)
}
},
"string" -> {
(json: JsValue) => Try[(Clazz) => Clazz] =
Try {
val s: String = json
(c: Clazz) => c.copy(string = s)
}
}
)
当我打电话给纽芬时,它将是一个失败者
val fun: (JsValue) => Try[(Clazz) => Clazz] = copyMap.get("int").get
val newFun: Try[(Clazz) => Clazz] = fun(JsString("non_int_input"))
这方面的宏代码是,我在c.universe中遇到了与Try的导入冲突。\因此使用了scala.util.Try
@EugeneBurmako我在上面添加了宏代码,以演示触发解析错误的含义——调用case类Clazzi:Int;copyMap[Clazz].geti.getJsStringcan not parse as Int将返回失败,因为无法使用隐式转换将JsValue解析为Int
val fun: (JsValue) => Try[(Clazz) => Clazz] = copyMap.get("int").get
val newFun: Try[(Clazz) => Clazz] = fun(JsString("non_int_input"))
import play.api.libs.json._
import scala.language.experimental.macros
object Macros {
implicit def jsonToInt(json: JsValue): Int = json.as[Int]
implicit def jsonToIntOpt(json: JsValue): Option[Int] = json.asOpt[Int]
implicit def jsonToStr(json: JsValue): String = json.as[String]
implicit def jsonToStrOpt(json: JsValue): Option[String] = json.asOpt[String]
def copyMap[T]: Map[String, (JsValue) => scala.util.Try[(T) => T]] = macro copyMapImpl[T]
def copyMapImpl[T: c.WeakTypeTag](c: scala.reflect.macros.Context):
c.Expr[Map[String, (JsValue) => scala.util.Try[(T) => T]]] = {
import c.universe._
val tpe = weakTypeOf[T]
val fields = tpe.declarations.collectFirst {
case m: MethodSymbol if m.isPrimaryConstructor => m
}.get.paramss.head
val methods = fields.map {
field => {
val name = field.name
val decoded = name.decoded
val fieldType = field.typeSignature.typeSymbol
val fieldTypeName = fieldType.name.decoded
q"""{$decoded -> {
(json: JsValue) => scala.util.Try {
val x: $fieldType = json
(t: $tpe) => t.copy($name = x)
}.recoverWith {
case e: Exception => scala.util.Failure(
new IllegalArgumentException("Failed to parse " + Json.stringify(json) + " as " + $decoded + ": " + $fieldTypeName)
)
}
}}"""
}
}
c.Expr[Map[String, (JsValue) => scala.util.Try[(T) => T]]] {
q"Map(..$methods)"
}
}
}