【问题标题】:How to enforce strict serialization of JSON in Play 2.x如何在 Play 2.x 中强制执行 JSON 的严格序列化
【发布时间】:2014-06-11 10:55:31
【问题描述】:

从 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?

【问题讨论】:

    标签: json scala playframework-2.0


    【解决方案1】:

    您可以在执行自己的解码之前验证对象不包含额外的密钥:

    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)
    

    重复不是很好,但很有效。

    【讨论】:

    • 想知道你今天是否会以不同的方式来添加更多的编译时间魔法来获得case class 属性名称与onlyFields("name", "value") 可变参数函数? onlyFields 中的硬编码属性名称方法有效,但遇到维护挑战,以记住在修改 case class 时更新/添加/删除 onlyFields 中的字段名称,因为 onlyFields 没有编译时安全性它不会显示丢失的属性直到单元测试/运行时。有没有办法在编译时实现这一点?
    • 你绝对可以用宏来做到这一点,或者用 Shapeless 的LabelledGeneric 更干净。我会试着找点时间写一篇博客文章来解决这个问题LabelledGeneric,但我不能保证这周会写完。
    【解决方案2】:

    受到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)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 2014-05-26
      • 2012-05-15
      • 1970-01-01
      • 2017-06-21
      • 2015-11-12
      • 2022-06-29
      相关资源
      最近更新 更多