I am writing a Play 2.3 application that serves JSON backed by mongodb. Some of the documents coming from the database contain sensitive fields. I want to be able to work with these documents server side but send a limited JSON view to clients. The documentation on Reads/Writes combinators discusses defining implicit Reads and Writes which works fine for sending data to and from the database but does not completely fill my needs.
What I want to do is define any number of additional Writes that I can use like json "views" to send particular transformations or subsets of models to clients. In Rails I use JBuilder for this purpose.
Trying to explicitly pass a different Writes to toJson does not give me the expected behavior. Take this simple controller action which should write a JSON array of all user ids and usernames:
def listUsers = Action.async {
    val testCustomWrite: Writes[User] = (
      (__ \ "id").write[String] and
      (__ \ "username").write[String]) { user: User =>
        (user._id.toString(), user.username)
      }
    UserDao.findAll().map {
      case Nil => Ok(Json.toJson(""))
      case users => Ok(Json.toJson(users)(testCustomWrite))
    }
  }
This fails to compile with
type mismatch;
[error]  found   : play.api.libs.json.Writes[models.User]
[error]  required: play.api.libs.json.Writes[List[models.User]]
[error]       case users => Ok(Json.toJson(users)(testCustomWrite))
The way toJson handles writing a list of objects depends on an implicit writer for arrays which depends on an implicit writer for a type. I could rewrite the above to to be val testCustomWrite: Writes[List[User]] but that does not feel like the correct solution because Play already provides an array wrapper for implicit writes.
Is there a preferred way to render multiple JSON "views" in Play2?
When passing the Writes explicitly, the type has to match. In this case you can use Writes.list:
Json.toJson(users)(Writes.list(testCustomWrite))
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With