【问题标题】:How to parse JSON empty string as `None` using Play Json?如何使用 Play Json 将 JSON 空字符串解析为“None”?
【发布时间】:2017-03-28 06:11:19
【问题描述】:

我有一个案例类,它是一个“字段袋”——许多字段代表一个业务实体。对于我的用例,""nullk/v 完全不在 JSON 对象中的区别与我无关。在这个案例类中,这些字段已经是 Option[String]s,所以我希望所有 3 个案例都合并到 None。我相信自动生成的Reads 的当前行为是我想要的,除了空字符串的情况。

这个 BOF 将来可能会改变,所以“只需实现你自己的 Reads”(如这里建议的那样:make play-json read the empty string as None for a type of Option[T])或其他我必须重新枚举所有字段的东西是行不通的.

我想我可能需要的是 Play 的“Json Transformers”。编写一个如果条目为空值则删除条目的转换器似乎微不足道,但我不知道如何将其与自动生成的 Reads 实现组合在一起。

我想我需要的是Reads 和转换器之上的一些组合器,一些签名,例如:(JSON -> JSON, JSON -> T) -> (JSON -> T)。显然,我找到了这个页面:https://www.playframework.com/documentation/2.5.x/ScalaJsonCombinators,但是列出的组合器都没有我想要的。这个组合器可以很容易地实现吗?我会有点超出我的 type-fu 深度,但如果我能得到一些指示,那将是一个很好的解决方案。

【问题讨论】:

    标签: json scala playframework


    【解决方案1】:

    这对我有用:

    class RemoveEmpty[T] (reader: Reads[T]) extends Reads[T] {
      override def reads(json: JsValue): JsResult[T] = json match {
        case JsObject(underlying) => { 
          reader.reads(JsObject(underlying.filterNot{ case (k, v) => jsonValueEmpty(v) } ))
        }
        case _ => { 
          JsError("Non-JsObj passed to RemoveEmpty")
        }
      }
    
      def jsonValueEmpty(v: JsValue) = v match {
        case JsNull | JsString("") => true
        case _ => false
      }
    }
    

    那么你可以像这样使用它:

    implicit val myTypeReads = new RemoveEmpty(Json.reads[MyType])
    

    【讨论】:

    • FWIW 在这个函数得到大量使用之后,我从未见过错误案例发生 - 我认为 Play 不知何故很聪明,我不太了解它的 JSON 解析的内部结构
    • 太酷了!但是它不适用于implicit val myTypeReads = new RemoveEmpty(play.api.libs.json.Reads.localDateTimeReads(DateTimeFormatter.ISO_DATE_TIME));它会抛出“非 JsObj 传递给 RemoveEmpty”错误。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 2011-03-14
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    • 2012-10-16
    相关资源
    最近更新 更多