字符串到类型的映射

时间:2017-09-04 18:04:57

标签: scala reflection types

我目前正在尝试编写一个采用JSON的方法(这里的API无关紧要)并验证它。我希望该方法看起来像这样:

def validateJson(json, expectedType: Map[String, Type(?)], allowedVals: Map[String, Seq[expectedType(key)]]): Boolean

问题是:我确实有方法jsonfield.validate[expectedType],但我不知道如何将与字符串相关联的未知数量的可用类型参数传递给方法。

如果可以在这里使用,我很乐意使用一些运行时反射,或者使这项工作变得简单所需的任何高级功能。任何建议表示赞赏。

PS:我正在使用Play Framework 2.6.3

修改 我正在尝试使用像这样的传递类型

val allowed = allowedVals(field) // a Set
// if field contents contained in allowed value set...
if( allowed(field.validate[expectedType(field)].get) ) foo 

1 个答案:

答案 0 :(得分:1)

也许您可以在运行时使用varargs或在编译时使用abstract over arity或只使用HList:

def foo[L <: HList](l: L) = ???

trait A
trait B
trait C
val a: A = new A {}
val b: B = new B {}
val c: C = new C {}

foo[A :: B :: C :: HNil](a :: b :: c :: HNil)

听起来像是在寻找dependent type /依赖函数/ polymorphic function

import shapeless.Poly1
import shapeless.syntax.singleton._

object expectedTypeAndValue extends Poly1 {
  implicit val aCase: Case.Aux["a", Int] = at["a"](_ => 1)
  implicit val bCase: Case.Aux["b", Long] = at["b"](_ => 2L)
  implicit val cCase: Case.Aux["c", Double] = at["c"](_ => 3.0)
}

def validateJson(json: Json): Boolean = {
  val x: Long = expectedTypeAndValue["b"]("b".narrow)
  ???
}
<{3>}或

中的

import shapeless.{Poly1, Witness}
import shapeless.syntax.singleton._

object expectedTypeAndValue extends Poly1 {
  implicit val aCase: Case.Aux[Witness.`"a"`.T, Int] = at[Witness.`"a"`.T](_ => 1)
  implicit val bCase: Case.Aux[Witness.`"b"`.T, Long] = at[Witness.`"b"`.T](_ => 2L)
  implicit val cCase: Case.Aux[Witness.`"c"`.T, Double] = at[Witness.`"c"`.T](_ => 3.0)
}

def validateJson(json: Json): Boolean = {
  val x: Long = expectedTypeAndValue[Witness.`"b"`.T]("b".narrow)
  ???
}

在Lightbend Scala(普通Scala)中。

您还可以创建自定义类型类:

  trait ExpectedTypeAndVals[S <: String] {
    type Out
    def apply(s: S): Set[Out]
  }

  object ExpectedTypeAndVals {
    type Aux[S <: String, Out0] = ExpectedTypeAndVals[S] {type Out = Out0}

    implicit def mkExpectedTypeAndVals[S <: String]: ExpectedTypeAndVals.Aux[S, ???] =
      new ExpectedTypeAndVals[S] {
        override type Out = ???
        override def apply(s: S): Set[Out] = ???
      }
  }

  def allowed[S <: String, Out](json: Json)(implicit
                                            typeAndVals: ExpectedTypeAndVals.Aux[S, Out]
  ): Boolean = {
    val str: S = ???
    val set: Set[Out] = typeAndVals(str)
    ???
  }

  if(allowed(json)) {
    ???
  }