2017-09-04 182 views
0

我目前正在尝试编写一个采用JSON(这里没有什么API)并验证它的方法。我想该方法看起来是这样的:字符串映射到类型

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

的问题是:我有一个方法jsonfield.validate[expectedType],但我不知道如何通过未知数量的与字符串相关的可用类型参数一个方法。

我很乐意使用一些运行时反射,如果这是可能的话,或任何高级功能,使这项工作很容易。任何建议感激。

PS:我用的播放框架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 
+0

而是使用密封式的家庭 – cchantep

回答

1

也许你可以在运行时或 abstract over arity使用 varargs在编译时或仅使用一个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) 
    ??? 
} 

Typelevel Scala

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斯卡拉(普通斯卡拉)。


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

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)) { 
    ??? 
    } 
+0

这听起来像我不得不通过位置在列表类型和字符串之间的关联,这是不是最佳。但没有形状的声音就像是正确的方向。任何关于如何获得关联的想法? – Dracam

+0

@Dracam我更新了我的答案。 –

+0

为初学者(或两者)添加快速说明或有用的参考将是惊人的,谢谢! – Dracam