简体   繁体   中英

Using multiple Writes with Play JSON to render different views of an object

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))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM