Reputation: 1071
I have following class and Reads Writes for json parsing / writeing
import play.api.libs.json._
import play.api.libs.functional.syntax._
import scala.collection.immutable.{Seq => ISeq, Set => ISet}
case class FileExcInc( isExclude: Boolean, isFile: Boolean, pattern: String) { }
implicit val fEIReads: Reads[FileExcInc] = (
(__ \ "isExclude").read[Boolean] and
(__ \ "isFile").read[Boolean] and
(__ \ "pattern").read[String]
)(FileExcInc.apply _)
implicit val fEIWrites: Writes[FileExcInc] = (
(__ \ "isExclude").write[Boolean] and
(__ \ "isFile").write[Boolean] and
(__ \ "pattern").write[String]
)(unlift(FileExcInc.unapply))
case class DirConf(sourceDir: String, csdataFile: String, fileExcIncSeq: ISeq[FileExcInc]) { }
implicit val dCReads: Reads[DirConf] = (
(__ \ "sourceDir").read[String] and
(__ \ "csdataFile").read[String] and
(__ \ "fileExcIncSeq").read[ISeq[FileExcInc]]
)(DirConf.apply _)
implicit val dCWrites: Writes[DirConf] = (
(__ \ "sourceDir").write[String] and
(__ \ "csdataFile").write[String] and
(__ \ "fileExcIncSeq").write[ISeq[FileExcInc]]
)(unlift(DirConf.unapply))
This compiles OK, but the following does not:
case class Conf(dirConfSeq: ISeq[DirConf]) { }
implicit val cReads: Reads[Conf] = (
(__ \ "dirConfSeq").read[ISeq[DirConf]]
)(Conf.apply _)
implicit val cWrites: Writes[Conf] = (
(__ \ "dirConfSeq").write[ISeq[DirConf]]
)(unlift(Conf.unapply))
It produces following error:
[info] Compiling 17 Scala sources and 1 Java source to /home/jk/workspace/Gen/target/scala-2.12/classes...
[error] /home/jk/workspace/Gen/src/main/scala/com/example/CTool.scala:341: overloaded method value read with alternatives:
[error] (t: scala.collection.immutable.Seq[com.example.CTool.DirConf])play.api.libs.json.Reads[scala.collection.immutable.Seq[com.example.CTool.DirConf]] <and>
[error] (implicit r: play.api.libs.json.Reads[scala.collection.immutable.Seq[com.example.CTool.DirConf]])play.api.libs.json.Reads[scala.collection.immutable.Seq[com.example.CTool.DirConf]]
[error] cannot be applied to (scala.collection.immutable.Seq[com.example.CTool.DirConf] => com.example.CTool.Conf)
[error] (__ \ "dirConfSeq").read[ISeq[DirConf]]
[error] ^
[error] /home/jk/workspace/Gen/src/main/scala/com/example/CTool.scala:345: overloaded method value write with alternatives:
[error] (t: scala.collection.immutable.Seq[com.example.CTool.DirConf])(implicit w: play.api.libs.json.Writes[scala.collection.immutable.Seq[com.example.CTool.DirConf]])play.api.libs.json.OWrites[play.api.libs.json.JsValue] <and>
[error] (implicit w: play.api.libs.json.Writes[scala.collection.immutable.Seq[com.example.CTool.DirConf]])play.api.libs.json.OWrites[scala.collection.immutable.Seq[com.example.CTool.DirConf]]
[error] cannot be applied to (com.example.CTool.Conf => scala.collection.immutable.Seq[com.example.CTool.DirConf])
[error] (__ \ "dirConfSeq").write[ISeq[DirConf]]
What's wrong in the last Reads, Writes? How to create Reads, Writes for class having just one field?
Upvotes: 3
Views: 825
Reputation: 3251
To create a Reads
/Writes
for a case class with just one field, use map
and contramap
to convert the field to and from the case class.
implicit val cReads: Reads[Conf] =
(__ \ "dirConfSeq").read[ISeq[DirConf]].map(Conf)
implicit val cWrites: Writes[Conf] =
(__ \ "dirConfSeq").write[ISeq[DirConf]].contramap(_.dirConfSeq)
Even easier is to use the Json.format
macro to generate all of the Reads
/Writes
boilerplate. It handles case classes with any number of fields provided the field names match the JSON. A Format[T]
is both a Reads[T]
and a Writes[T]
.
implicit val fEIFormat: Format[FileExcInc] = Json.format[FileExcInc]
implicit val dCFormat: Format[DirConf] = Json.format[DirConf]
implicit val cFormat: Format[Conf] = Json.format[Conf]
See: https://www.playframework.com/documentation/2.6.x/ScalaJsonAutomated
Upvotes: 2