How to implement implicit Json Writes of embedded object in Play Framework 2.x
It's a question of visibility, when declaring the implicit Writes[Foo] you are not making visible the implicit Writes[Bar] to it:
scala> :paste// Entering paste mode (ctrl-D to finish)import play.api.libs.json._case class Bar(x: String, y: Int)object Bar { implicit val implicitBarWrites = new Writes[Bar] { def writes(bar: Bar): JsValue = { Json.obj( "x" -> bar.x, "y" -> bar.y ) } }}case class Foo(id: String, bar: Bar)object Foo { import Bar._ implicit val implicitFooWrites = new Writes[Foo] { def writes(foo: Foo): JsValue = { Json.obj( "id" -> foo.id, "bar" -> foo.bar ) } } }// Exiting paste mode, now interpreting.import play.api.libs.json._defined class Bardefined module Bardefined class Foodefined module Fooscala> Json.prettyPrint(Json.toJson(Foo("23", Bar("x", 1))))res0: String = { "id" : "23", "bar" : { "x" : "x", "y" : 1 }}
Also, if you're using Play 2.1+ make sure to check out the brand new use of 2.10's macros: http://www.playframework.com/documentation/2.1.0/ScalaJsonInception
If you're happy with the use of the case classes and the val/vars' names being used as keys in the json output, as in your case BTW, then you can use the two one-liners:
implicit val barFormat = Json.writes[Bar]implicit val fooFormat = Json.writes[Foo]
That will give you the exact equivalent:
scala> import play.api.libs.json._import play.api.libs.json._scala> case class Bar(x: String, y: Int)defined class Barscala> case class Foo(id: String, bar: Bar)defined class Fooscala> implicit val barWrites = Json.writes[Bar]barWrites: play.api.libs.json.OWrites[Bar] = play.api.libs.json.OWrites$$anon$2@257cae95scala> implicit val fooWrites = Json.writes[Foo]fooWrites: play.api.libs.json.OWrites[Foo] = play.api.libs.json.OWrites$$anon$2@48f97e2ascala> Json.prettyPrint(Json.toJson(Foo("23", Bar("x", 1))))res0: String = { "id" : "23", "bar" : { "x" : "x", "y" : 1 }}