thelemens
thelemens

Reputation: 11

Play Json: reading multiple optional nested objects

We have a case class and Json combinators similar to the below:

case class Thing(param1: Option[BigDecimal],
                 param2: Option[BigDecimal])

object Thing {
  implicit val writes: Writes[Thing] = Json.writes[Thing]

  implicit val reads: Reads[Thing] = (
    (__ \ "parent" \ "param1").readNullable[BigDecimal] and
    (__ \ "param2").readNullable[BigDecimal]
    )(Thing.apply _)

The Json reads combinator for Thing will handle incoming Json matching the below:

{ 
    "parent": {
        "param1: 1111.11
     },
    "param2": 2222.22
}

The standard ReadNullable works as we need it to when param1 is not present, resulting in the creation of Thing(None, 2222.22). However the parent object is also optional, and reading the path explicitly like the above results in a path missing exception if it does not exist. We need this to result in a Thing(None, 2222.22), the same as if the param1 field wasn't present.

We could use a recursive read such as (__ \\ "param1") to bipass this exception, but ideally we would like to preserve the explicit path as there are other Json objects that have similar, if not identical fields at the same level.

Is this possible by using Json combinators in this way?

Upvotes: 1

Views: 312

Answers (2)

C4stor
C4stor

Reputation: 8026

You can replace .readNullable[BigDecimal] with read(Reads.optionNoError[BigDecimal]) to map errors to None.

Upvotes: 0

Shweta Valunj
Shweta Valunj

Reputation: 158

You can do in following way by creating two case classes.
case class Thing(param1: Option[BigDecimal])
case class ParentJson(parent: Option[Thing], param2: Option[BigDecimal])

Upvotes: 1

Related Questions