问题描述
我是scala的新手。我有一个参数,可以是字符串,布尔值或数字。我不知道哪种数据类型会出现。早些时候,我有以下代码。
Try {
JsNumber(parameter._x.trim())
} match {
case Success(success) => myMethod(JsNumber(parameter._x.trim()))
case Failure(ex) => myMethod(Jsstring(parameter._x.trim())
}
如果传入的参数值为数字,则成功时将JsNumber
传递给方法,否则将传递给Jsstring
。现在,我也可以将Boolean
和String
作为传入类型作为值。我该如何编写通用代码来将具有适当类型的适当值传递给方法?
解决方法
对我认为您的API进行反向工程,我猜它可以在以下环境下工作:
val paramString = parameter._2.trim
val asJval = Try(JsNumber(paramString))
.orElse(Try(JsBoolean(paramString)))
.getOrElse(JsString(paramString))
asJval.map(myMethod)
提醒您,我不知道parameter
,myMethod
的类型,也不知道JsNumber.apply
的签名,或者JsNumber.apply
是否JsBoolean.apply
存在:我只是在猜测它可能基于常见模式。
如果只想支持原语,则可以具有以下内容:
def convertToJsValue(element: Any): JsValue = element match {
case s: String => JsString(s)
case number: Int => JsNumber(number)
case b: Boolean => JsBoolean(b)
case arr: Seq[Any] => JsArray(arr.map(convertToJsValue))
case map: Map[String,Any] => JsObject(map.mapValues(convertToJsValue))
case other => throw new UnsupportedOperationException(s"Type ${other.getClass.getName} is not supported.")
}
拨打以下电话时:
println(Json.stringify(convertToJsValue("aa")))
println(Json.stringify(convertToJsValue(55)))
println(Json.stringify(convertToJsValue(true)))
println(Json.stringify(convertToJsValue(Seq(0,1,"aa",true))))
println(Json.stringify(convertToJsValue(Map("IntKey" -> 1,"StringKey" -> "aa","BooleanKey" -> true))))
case class A(x: Int)
输出为:
"aa"
55
true
[0,true]
{"IntKey":1,"StringKey":"aa","BooleanKey":true}
Exception in thread "main" java.lang.UnsupportedOperationException: Type HelloWorld1$A is not supported.
当然列表和数组可以嵌套。
如果还要支持案例类,则需要添加隐式格式,例如:
object A {
implicit val format: OFormat[A] = Json.format[A]
}
并添加一个与模式匹配的案例:
case a: A => Json.toJson(a)
结果:
println(Json.stringify(convertToJsValue(A(10))))
将是:
{"x":10}
,
据我了解,您正在尝试使用Json来解决您的myMethod
要求。
您可以代替第二个参数创建ADT,而不必使用Json。
trait SecondParameter
object SecondParameter {
case class WrappedInt(value: Int) extends SecondParameter
case class WrappedBoolean(value: Boolean) extends SecondParameter
case class WrappedString(value: String) extends SecondParameter
val intRegex = "[0-9]+".r
def apply(string: String): SecondParameter =
if (intRegex.matches(string))
WrappedInt(string.toInt)
else if (string.equals("true"))
WrappedBoolean(true)
else if (string.equals("false"))
WrappedBoolean(false)
else
WrappedString(string)
}
def myMethod(first: String,second: SecondParameter,third: String): Unit = {
second match {
case SecondParameter.WrappedInt(i) => println(s"int :: $i")
case SecondParameter.WrappedBoolean(b) => println(s"boolean :: $b")
case SecondParameter.WrappedString(s) => println(s"string :: $s")
}
}
myMethod(parameter._1,SecondParameter(parameter._2),parameter._3)