user4955663
user4955663

Reputation: 1071

Scala json parsing for single field class

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

Answers (1)

Rich Dougherty
Rich Dougherty

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

Related Questions