Search code examples
scalaplayframeworkplay-json

How write Reads function for Scala Play


I have problem with Reads. I have function like this:

  private val myFunc: Reads[Foo] =
    (__ \ "foo")
      .readNullable[Foo]
      .map {
        case Some(foo) => foo
        case None =>
          (__ \ "bar").readNullable[Bar].map {
            case Some(bar) => Foo(bar.value)
            case None => Foo("")
          }
      }

But I getting compiler problem like this:

[error]  found   : play.api.libs.json.Reads[com.me.Foo]
[error]  required:com.me.Foo

How I fix this?


Solution

  • import play.api.libs.json._
    
    case class Foo(lorem: String)
    
    implicit val fooReads: Reads[Foo] = Json.reads[Foo]
    
    case class Bar(value: String)
    
    implicit val barReads: Reads[Bar] = Json.reads[Bar]
    
    val reads: Reads[Foo] = (__ \ "foo").read[Foo].orElse {
      (__ \ "bar").readNullable[Bar].map {
        case Some(bar) => Foo(bar.value)
        case None => Foo("")
      }
    }
    
    // ---
    
    Json.parse("""{"foo":{"lorem":"ipsum"}}""").validate(reads)
    // JsSuccess(Foo(ipsum),/foo)
    
    Json.parse("""{"bar":{"value":"ipsum"}}""").validate(reads)
    // JsSuccess(Foo(ipsum),/bar)
    

    As there is no value in instantiating Bar in the orElse:

    val reads: Reads[Foo] = (__ \ "foo").read[Foo].orElse {
      (__ \ "bar" \ "value").readNullable[String].map {
        case Some(bar) => Foo(bar)
        case None => Foo("")
      }
    }