Reputation: 101
I've got a case class with some optionals:
case class Person (
name: String,
nationality: Option[String],
email: Option[String],
gender: Option[String]
)
Using play 2.1.3 I'm trying to create a JSON looking like:
{"name": "Joe", "email": "[email protected]"}
for an object:
val user = new User("Joe, None, Some("[email protected]"), Some("male"))
with:
val myJson = Json.obj("name" -> user.name,
"nationality" -> user.nationality, "email" -> user.email)
I however get:
{"name": "Joe", "nationality": null, "email": "[email protected]"}
How can I avoid the nationality with null value in the JSON?
Upvotes: 5
Views: 2480
Reputation: 4027
I know that it is an extremely late response and it doesn't apply in the original context, but it might be useful nowadays. I have this working in Scala 3.3.1 & Play 3.0:
implicit val personWrites: Writes[Person] = new Writes[Person] {
def writes(o: StudentMarkRow): JsValue =
val builder = Json.newBuilder
builder += "name" -> o.name
if o.nationality.isDefined then builder += "nationality" -> o.nationality.get
if o.email.isDefined then builder += "email" -> o.email.get
if o.gender.isDefined then builder += "gender" -> o.gender.get
builder.result()
}
One could abstract away the pattern if o.gender.isDefined then builder += "gender" -> o.gender.get
maybe as an extension method to Builder trait.
Upvotes: 0
Reputation: 101
After realizing that the problem was related to the play JSON handling, I managed to find a solution inspired by I need advice on Play's Json and elegant Option handling in the Writes trait. I'm not convinced that this is the most elegant solution out there, but it works:
def writes(person: Person): JsValue = {
JsObject(
Seq[(String, JsValue)]() ++
Some(person.name).map("name" -> JsString(_)) ++
person.email.map("email" -> JsString(_))
)
}
Upvotes: 5