Reputation: 3867
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
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