简体   繁体   中英

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. In this case class these fields are already Option[String] s, so I'd like all 3 of those cases to collapse into None . I believe the current behavior of the auto-generated Reads is what I want except for the empty string case.

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.

I think what I may need is Play's 'Json Transformers'. 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.

I imagine what I need is some combinator over Reads and transformers, some signature like: (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. 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])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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