CustardBun
CustardBun

Reputation: 3867

Play framework: Reading possibily null value into string "null" instead of Option[String]

My issue is similar to this one: Play framework: read Json containing null values

implicit val readObj: Reads[ApplyRequest] = (
  (JsPath \ "a").read[String] and
  (JsPath \ "b").readNullable[String] and
  (JsPath \ "c").readNullable[String] and
  (JsPath \ "d").readNullable[Int]
)  (ApplyRequest.apply _)

Except instead of parsing a potentially null value into an Option[String], I would like one of these values to be a String, but allow the value being parsed in to be the string "null" if the value is absent or null.

ie.

implicit val readObj: Reads[ApplyRequest] = (
  (JsPath \ "a").read[String] and
  (JsPath \ "b").read[String] and // this can be null, but should turn into string "null"
  (JsPath \ "c").readNullable[String] and
  (JsPath \ "d").readNullable[Int]
)  (ApplyRequest.apply _)

Is this possible? What's a clean way of doing this?

We're unfortunately using version 2.4 so don't have the default behavior in 2.6

Upvotes: 0

Views: 887

Answers (1)

Antot
Antot

Reputation: 3964

Yes, this is possible by using the readWithDefault method.

Having:

case class ApplyRequest(a: String, b: String, c: Option[String], d: Option[Int])

private val json =
"""
  |{
  |  "a": "test1",
  |  "b": null,
  |  "c": null,
  |  "d": 1
  |}
""".stripMargin

The Reads is defined:

implicit val readObj: Reads[ApplyRequest] = (
    (JsPath \ "a").read[String] and
    (JsPath \ "b").readWithDefault[String]("null") and // default value here
    (JsPath \ "c").readNullable[String] and
    (JsPath \ "d").readNullable[Int]
  ) (ApplyRequest.apply _)

Parsed:

val parsedJsValue = Json.parse(json)
val parsedApplyRequest = Json.fromJson[ApplyRequest](parsedJsValue).get
println(parsedApplyRequest)            // ApplyRequest(test1,null,None,Some(1))
println(parsedApplyRequest.b.getClass) // class java.lang.String

Upvotes: 1

Related Questions