[英]How to parse JSON empty string as `None` using Play Json?
I have a case class that's a "Bag of Fields" - lots of fields that represent a business entity. 我有一个案例类,它是一个“字段包”-许多表示业务实体的字段。 For my use case, the distinction between
""
, null
, and the k/v
being totally absent from the JSON object is irrelevant to me. 就我的用例而言,
""
, null
和JSON对象中完全不存在的k/v
之间的区别与我无关。 In this case class these fields are already Option[String]
s, so I'd like all 3 of those cases to collapse into None
. 在这种情况下,这些字段已经是
Option[String]
,所以我希望所有这三种情况都折叠为None
。 I believe the current behavior of the auto-generated Reads
is what I want except for the empty string case. 我相信自动生成的
Reads
的当前行为是我想要的,除了空字符串情况。
This BOF is likely to change in the future, so "just implement your own Reads
" (as suggested here: make play-json read the empty string as None for a type of Option[T] ) or something else where I have to re-enumerate all the fields is a non-starter. 此BOF将来可能会更改,因此“只需实现您自己的
Reads
”(如此处建议: 使play-json将空字符串读取为Option [T]类型的None即可 )或其他必须重新设置的内容-枚举所有字段不是入门者。
I think what I may need is Play's 'Json Transformers'. 我认为我可能需要Play的“ Json变形金刚”。 It appears trivial to write a transformer that removes entries if they have empty values, but what I cant figure out is how to compose it with the auto-generated
Reads
implementation. 编写一个转换器来删除条目(如果它们具有空值)似乎很简单,但是我不知道是如何与自动生成的
Reads
实现一起编写的。
I imagine what I need is some combinator over Reads
and transformers, some signature like: (JSON -> JSON, JSON -> T) -> (JSON -> T)
. 我想象我需要的是一些在
Reads
和Reads
组合器,一些签名,例如: (JSON -> JSON, JSON -> T) -> (JSON -> T)
。 Obviously I've found this page: https://www.playframework.com/documentation/2.5.x/ScalaJsonCombinators , but none of the listed combinators does what I want I believe. 显然,我找到了以下页面: https : //www.playframework.com/documentation/2.5.x/ScalaJsonCombinators ,但是列出的组合器都没有我想要的。 Could this combinator be easily implemented?
这个组合器可以容易实现吗? I'd be a little out of my type-fu depth but that would be a great solution if I could get some pointers.
我可能会有点不适应类型,但是如果我能得到一些指导的话,那将是一个很好的解决方案。
Here's what worked for me: 这对我有用:
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
}
}
Then you can just use it like this: 然后,您可以像这样使用它:
implicit val myTypeReads = new RemoveEmpty(Json.reads[MyType])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.