Not sure if cross-posting is ok, but trying my luck here…
Upon reading JSON documents in play-json, it seems the code generated by the macros expects sequences to be enclosed in an Option if they may be empty. Is there a way to prevent this?
Thanks!
Does this really go for empty collections, or null/absence of a collection?
Actually I had only tried with an absent value, but it turns it the same problem occurs with null
but not []
The following illustrates the problem (this excerpt runs sucessfully):
import play.api.libs.json._
case class Foo1(bar: String, baz: Seq[Int])
case class Foo2(bar: String, baz: Option[Seq[Int]])
implicit val FormatFoo1 = Json.format[Foo1]
implicit val FormatFoo2 = Json.format[Foo2]
def main(args: Array[String]): Unit = {
assert(Json.fromJson[Foo1](Json.parse("""{"bar":"hello","baz":[1, 2, 3]}""")).isSuccess)
assert(Json.fromJson[Foo1](Json.parse("""{"bar":"hello","baz":[] }""")).isSuccess)
assert(Json.fromJson[Foo1](Json.parse("""{"bar":"hello","baz":null }""")).isError )
assert(Json.fromJson[Foo1](Json.parse("""{"bar":"hello" }""")).isError )
assert(Json.fromJson[Foo2](Json.parse("""{"bar":"hello","baz":[1, 2, 3]}""")).isSuccess)
assert(Json.fromJson[Foo2](Json.parse("""{"bar":"hello","baz":[] }""")).isSuccess)
assert(Json.fromJson[Foo2](Json.parse("""{"bar":"hello","baz":null }""")).isSuccess)
assert(Json.fromJson[Foo2](Json.parse("""{"bar":"hello" }""")).isSuccess)
}
That seems correct to me as default behaviour: no collection is different from an empty collection.
Manually creating the Reads
instance would work around. myopt.getOrElse(Nil)
for example will flatten an Option[Seq[A]]
into a List[A]
You’re right that I should rephrase my question, in that it’s not a “problem” with play-json.
Basically I was hoping for a workaround, one that would still allow me to use the macros (else it quickly becomes very verbose). But I suspect it’s going to be more work than just wrapping it in an Option
cbley
November 20, 2019, 8:45pm
6
The problem is: how should the case class be constructed if one of its parameters are missing?
What you could do, is to use default parameters:
case class Foo1(bar: String, baz: Seq[Int] = Seq.empty)
val implicit foo1Reads = Json.using[Json.MacroOptions with Json.DefaultValues].reads[Foo1]
3 Likes
Very nice thanks! I think that might be just what I needed. It’s unfortunate the documentation for the Macros doesn’t mention .using
godenji
November 28, 2020, 3:22am
8
Yes!!! Wrapping possibly empty collections in Option begone.
Option[List[T]]
, just ughhhh, no.
Thanks