Using multiple Writes with Play JSON to render different views of an object
json, playframework, playframework-2.3, scala
Solution
When passing the `Writes` explicitly, the type has to match. In this case you can use `Writes.list`:
Json.toJson(users)(Writes.list(testCustomWrite))
Problem
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?