简体   繁体   English

如何在Play 2.x中强制执行严格的JSON序列化

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

Play's JSON serialization is by default permissive when serializing from JSON into a case class. 从JSON序列化为案例类时,Play的JSON序列化默认是允许的。 For example. 例如。

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

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

If the following JSON was received: 如果收到以下JSON:

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

It will succeed with a 'JsSuccess' and discard the 'extraField'. 它将通过'JsSuccess'成功并丢弃'extraField'。

Is there a way to construct the Json Reads function to have it return a JsError if there are 'unhandled' fields? 有没有办法构造Json Reads函数,以便在存在“未处理”字段时返回JsError?

You can verify that the object doesn't contain extra keys before performing your own decoding: 在执行自己的解码之前,您可以验证对象是否包含额外的键:

import play.api.data.validation.ValidationError

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

Or if you don't care about error messages (and that one's not very helpful, anyway): 或者,如果您不关心错误消息(无论如何,这不是很有帮助):

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

And then: 接着:

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

The repetition isn't very nice, but it works. 重复不是很好,但它的工作原理。

Inspired from Travis ' comment to use LabelledGeneric I was able achieve compile time safe solution. 灵感来自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

now keys.map (toStringName).toList will give you 现在keys.map (toStringName).toList会给你

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM