Reputation: 1490
I am writing a Play 2.3 application backed by mongodb which serves JSON to an angularjs client. The app is being ported from Rails and many of my existing mongo documents have more than 22 fields which prevented the use of Json.format macro to serialize them to/from case classes. I worked around that using shapeless from this gist (which I don't fully understand yet).
Now I am facing the problem of writing JSON "views" for the client. Not all of the data in my documents should be sent to the client -- hashed passwords and such. To send the correct data I am attempting to use a custom Writes but am running into the 21 field limit problem again. For example the following fails to compile:
val viewWrites: Writes[User] = (
(__ \ "id").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String] and
(__ \ "u").write[String]
) { user: User =>
(user._id.toString(),
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username,
user.username)
}
with the error
play.api.libs.functional.FunctionalBuilder[play.api.libs.json.OWrites]#CanBuild22[String,String,String,String,String,String,String,String,String,String,String,String,String,String,String,String,String,String,String,String,String,String] does not take parameters
If I remove one of those fields it will compile correctly. I realize that I could break the model down into several parts but I don't want to do that because:
How can I write arbitrarily sized JSON "views" to serve my exiting client in the format that it expects?
Upvotes: 1
Views: 773
Reputation: 559
declare your writes as follows:
implicit val viewWrites = new Writes[User] {
def writes(user: User) = Json.obj(
"id" -> user._id.toString(),
"u" -> user.username,
//repeat 20 times
"u" -> user.username)
}
Basically, you're manually creating the Writes[User] object, and explicitly defining a writes method that takes a single parameter of type User, and returns a JsObject. You can include/exclude fields as needed.
Upvotes: 1