How can I write and read an empty case class with play-json?

I have an empty case class corresponding to an HTTP GET request:

case class GetFoo() extends MyQueryRequest {
  // ...


and each message has a companion object describing its implicit writer and JSON reader:

object GetFoo extends MyImplicitJsonProvider[GetFoo] {
  implicit val write = Json.writes[GetFoo]
  implicit val read = Json.reads[GetFoo]


However, since GetFoo

it takes no parameters, there is no way to serialize it:

Object violation GetFoo

has no parameters. Are you using an empty class class?

A workaround for injecting a dummy boolean into the constructor for GetFoo

, but that's a kludge. I would like to make GetFoo

(de) serializable as an empty JSON object. How can i do this?

Since GET requests do not send data, it would be even better to make the broker / author an exception if used, since the request should never be written or read, but an extended class is required.

My design relies on a class GetX

that extends MyQueryRequest

as well as GetX

a companion object that extends MyImplicitJsonProvider[GetX]



source to share

1 answer

Throwing error

If you just want to have unimplemented implicit values, you can do very well

implicit def format: Format[GetFoo] = ???


This will add an implicit value to the scope when you need it, but will call NotImplementedException

if called.

Serialization dummy

If you want to (de) serialize as empty JsObject

, just do it as such:

implicit val nonStrictReads = Reads.pure(GetFoo()) // does not check anything on the `JsValue`, always give a `JsSuccess(GetFoo())`
implicit val strictReads = Reads[GetFoo](json => json.validate[JsObject].filter(_.values.isEmpty).map(_ => GetFoo())
implicit val writes = OWrites[GetFoo](_ => Json.obj())


You better catch him while you can

However, it would be better to catch the compile-time error by ensuring (through stronger typing) that your request does not contain content. For this I will need more information on MyQueryRequest

and MyImplicitJsonProvider

to help you, but I could do something like MyQueryRequest[NoContent]

or MyQueryRequest[JsValue]

depending on when you have some content or not. Then a JSON serializer would be required, and another would not.

By the way, you might want to replace the empty case class with a case object to avoid unnecessary multiple allocations (if you don't).



All Articles