簡體   English   中英

如何在Play 2.x中強制執行嚴格的JSON序列化

[英]How to enforce strict serialization of JSON in Play 2.x

從JSON序列化為案例類時,Play的JSON序列化默認是允許的。 例如。

case class Stuff(name: String, value: Option[Boolean])

implicit val stuffReads: Reads[Stuff] = (
  ( __ \ 'name).read[String] and
  ( __ \ 'value).readNullable[Boolean]
)(Stuff.apply _)

如果收到以下JSON:

{name: "My Stuff", value: true, extraField: "this shouldn't be here"}

它將通過'JsSuccess'成功並丟棄'extraField'。

有沒有辦法構造Json Reads函數,以便在存在“未處理”字段時返回JsError?

在執行自己的解碼之前,您可以驗證對象是否包含額外的鍵:

import play.api.data.validation.ValidationError

def onlyFields(allowed: String*): Reads[JsObject] = Reads.filter(
  ValidationError("One or more extra fields!")
)(_.keys.forall(allowed.contains))

或者,如果您不關心錯誤消息(無論如何,這不是很有幫助):

def onlyFields(allowed: String*): Reads[JsObject] =
  Reads.verifying(_.keys.forall(allowed.contains))

接着:

implicit val stuffReads: Reads[Stuff] = onlyFields("name", "value") andThen (
  (__ \ 'name).read[String] and
  (__ \ 'value).readNullable[Boolean]
)(Stuff)

重復不是很好,但它的工作原理。

靈感來自Travis的使用LabelledGeneric的評論,我能夠實現編譯時安全的解決方案。

object toStringName extends Poly1 {
    implicit def keyToStrName[A] = at[Symbol with A](_.name)
}
case class Foo(bar: String, boo: Boolean)

val labl = LabelledGeneric[Foo]
val keys = Keys[labl.Repr].apply

現在keys.map (toStringName).toList會給你

res0: List[String] = List(bar, boo)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM