I am writing a Play 2.3 application that serves JSON supported by mongodb. Some of the documents coming from the database contain sensitive fields. I want to be able to work with these documents on the server side, but send a limited view of JSON to clients. The Reads / Writes compiler documentation discusses the definition of implicit Reads and Writes that work great for sending data to and from the database, but do not completely fill my needs.
What I want to do is to define any number of additional Writes that I can use as json "views" to send to certain transformations or subsets of models to clients. In Rails, I use JBuilder for this purpose.
Trying to explicitly pass different entries to toJson does not give 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 does not 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 handle writing a list of objects depends on the implicit writer for arrays, which depends on the implicit writer for the type. I could rewrite above to be val testCustomWrite: Writes[List[User]] , but this doesn't seem to be the right solution, because Play already provides an array wrapper for implicit entries.
Is there a preferred way to display multiple JSON "views" in Play2?
source share