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
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).
source to share