3

I'm trying to generalize one of the functions I use for returning Json from a Play action.

I currently do it like this:

def JsendOkObj(obj: JsValue) = Ok(Json.obj("status" -> "success", "data" -> obj))

and call it:

JsendOkObj(Json.toJson(myObj))

I'd like to do something more like:

def JsendOkObj[A](obj: A) = Ok(Json.obj("status" -> "success", "data" -> Json.toJson(obj)))

and then call it like:

JsendOkObj(myObj)

where Json.toJson is defined as:

def toJson[A](implicit arg0: Writes[A]): Enumeratee[A, JsValue]

The error I get compiling this is that I need to define a Writes for type A. Which is not possible here since I don't know which type A will actually end up being:

No Json deserializer found for type A. Try to implement an implicit Writes or Format for this type.

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
jl.
  • 752
  • 6
  • 19

1 Answers1

12

You can ensure that an implicit Writes[A] will be in scope when you call toJSon by adding an implicit parameter list to your own method, like this:

def JsendOkObj[A](obj: A)(implicit w: Writes[A]) =
  Ok(Json.obj("status" -> "success", "data" -> Json.toJson(obj)))

Which is equivalent to passing the type class instance explicitly to toJson:

def JsendOkObj[A](obj: A)(implicit w: Writes[A]) =
  Ok(Json.obj("status" -> "success", "data" -> Json.toJson(obj)(w)))

Note that you could also use a context bound here:

def JsendOkObj[A: Writes](obj: A) =
  Ok(Json.obj("status" -> "success", "data" -> Json.toJson(obj)))

This is just syntactic sugar for my first version above.

Community
  • 1
  • 1
Travis Brown
  • 138,631
  • 12
  • 375
  • 680