Reputation: 9724
Given the following case class
...
case class Address(
name: Option[String],
zip: String,
city: String
)
... I need to generate different JSON depending on whether or not name
is defined:
val selector = address.name.map { addressName =>
Json.obj(
userId.key -> userId.value,
"addresses.name" -> name,
"$or" -> Json.arr(
Json.obj(s"addresses.name" -> name),
Json.obj("addresses.name" -> Json.obj("$ne" -> addressName))
)
)
} getOrElse {
Json.obj(
userId.key -> userId.value,
"addresses.name" -> name
)
}
If you look at the code above, both blocks have a common part:
Json.obj(
userId.key -> userId.value,
"addresses.name" -> name
Is there any way to make the code more concise without repeating the common part?
Upvotes: 1
Views: 123
Reputation: 1786
There are two methods on JsObject
you can use: ++
or +
. The first one merges with another JsObject, the second one adds a new field.
val commonPart = Json.obj(
userId.key -> userId.value,
"addresses.name" -> name
)
val selector = address.name.map { addressName =>
commonPart + "$or" -> Json.arr(
Json.obj(s"addresses.name" -> name),
Json.obj("addresses.name" -> Json.obj("$ne" -> addressName))
)
} getOrElse(commonPart)
Using foldLeft:
val selector = address.name.foldLeft(Json.obj(userId.key -> userId.value, "addresses.name" -> name)) {
(commonPart, addressName) =>
commonPart + ("$or" -> Json.arr(
Json.obj(s"addresses.name" -> name),
Json.obj("addresses.name" -> Json.obj("$ne" -> addressName))
))
}
Upvotes: 1