Search code examples
scalaplayframeworkplay-json

JsValue filter out null values


I am trying to figure out how to avoid null values. My problem is, that I am querying an API and it returns a null value.

Here's an example:

import play.api.libs.json._

case class InnerExample(value: String)

object InnerExample {
def fromJson(json: JsValue) = InnerExample(
    value = (json \ "value")as[String]
}

case class Example(innerValue: Option[InnerExample])

object Example {
def fromJson(json: JsValue) = Example(
    optionalValue = (json \ "innerValue").asOpt[String].map(InnerExample.apply)
    )
}

The problem I am having is that asOpt transforms innerValue not to a None, but to a Some(null). I understand why and it makes a lot of sense. But I need to figure out a way to deal with it. Something more elegant than matching for Some(null). I am very grateful for any ideas.


Solution

  • Consider readNullable. Here is working example:

    import play.api.libs.json._
    
    case class InnerExample(value: String)
    case class Example(innerValue: Option[InnerExample])
    
    object InnerExample {
      implicit val format = Json.format[InnerExample]
    }
    
    object Example {
      implicit val jsonread: Reads[Example] =
        (JsPath \ "innerValue").readNullable[InnerExample].map(Example.apply)
    }
    
    object NullableJson extends App {
      val jsonSomeStr = """{ "innerValue": { "value": "woohoo" } }"""
      val jsonSome = Json.parse(jsonSomeStr).as[Example] 
      println(jsonSome) // Example(Some(InnerExample(woohoo)))
    
      val jsonNullStr = """{ "innerValue": null }"""
      val jsonNull = Json.parse(jsonNullStr).as[Example]
      println(jsonNull) // Example(None)
    }