2017-09-04 112 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

相關問題