Play JSON Version (2.5.x / etc)
3.0.1
API (Scala / Java / Neither / Both)
Scala
Problem
Map serialization/deserialization is broken if the key doesn't have a KeyReads instance.
The problem stems from the LowPriorityKeyReads.readableKeyReads which implies that if you have a Reads[A] then you have KeyReads[A], which does not seem like a logical conclusion. After all, the Reads can expect JsArray, JsObject or any other type, none of which are JsString.
import play.api.libs.json.*
val map = Map((1, 2) -> "foo")
val asJson = Json.prettyPrint(Json.toJson(map))
println(asJson)
// Gets serialized to: [ [ [ 1, 2 ], "foo" ] ]
val fromJson = Json.parse(asJson).validate[Map[(Int, Int), String]]
println(fromJson)
// Fails to deserialize, as a failing `KeyReads[(Int, Int)]` will be created from `LowPriorityKeyReads.readableKeyReads`
Suggested solution
Remove LowPriorityKeyReads.readableKeyReads. This breaks backwards compatibility, but I argue that this function is useless (as in it almost never produces a useful Reads instance anyway).
Reproducible Test Case
https://scastie.scala-lang.org/8ePgBH6lQ5i4GmCOPksvyw
Play JSON Version (2.5.x / etc)
3.0.1
API (Scala / Java / Neither / Both)
Scala
Problem
Map serialization/deserialization is broken if the key doesn't have a
KeyReadsinstance.The problem stems from the
LowPriorityKeyReads.readableKeyReadswhich implies that if you have aReads[A]then you haveKeyReads[A], which does not seem like a logical conclusion. After all, theReadscan expectJsArray,JsObjector any other type, none of which areJsString.Suggested solution
Remove
LowPriorityKeyReads.readableKeyReads. This breaks backwards compatibility, but I argue that this function is useless (as in it almost never produces a usefulReadsinstance anyway).Reproducible Test Case
https://scastie.scala-lang.org/8ePgBH6lQ5i4GmCOPksvyw