简体   繁体   中英

Is JSON formatting not enough for parsing case class having > 22 fields?

My case class has 30 fields. For simplicity, I use 4 fields,

case class Person(id: Long, name: String, age: Int, sex: Sex)

val personFormat1: OFormat[(Long, String)] = ((__ \ "id").format[Long] ~ (__ \ "name").format[String]).tupled
val personFormat2: OFormat[(Int, Sex)] = ((__ \ "age").format[Int] ~ (__ \ "sex").format[Sex]).tupled
implicit val personFormat: Format[Person] = (personFormat1 ~ personFormat2)({
  case ((id, name), (age, sex)) => new Person(id, name, age, sex)
}, (person: Format) => ((person.id, person.name), (person.age, person.sex)))

But even after writing formatter with format1 as a group of 22 fields and format2 as a group of 8 fields, I get error when am trying to parse the json of this case class.

Error is No Json serializer as JsObject found for type Person. Try to implement an implicit OWrites or OFormat for this type.

How to write implicit Owrites or OFormat? or how to fix this issue?

我使用Play-Json扩展库来处理超过22个字段的JSON: https : //github.com/xdotai/play-json-extensions

libraryDependencies += "ai.x" %% "play-json-extensions" % "0.8.0"

You need to an implicit writer to do this. Something like this

implicit val person= Json.format[Person]

Also, if you are using custom data types, like for your case Sex you need to specify a reader and writer. You do not need to do this for primitive types like Int, Long, String Etc.

  def enumReads[T <: Enum[T]](mkEnum: String => T) = new Reads[T] {
    override def reads(json: JsValue): JsResult[T] =
      json match {
        case JsString(s) => try {
          JsSuccess(mkEnum(s))
        }
        catch {
          case e: IllegalArgumentException =>
            JsError("Not a valid enum value: " + s)
        }
        case v => JsError("Can't convert to enum: " + v)
      }
  }

  implicit val enumWrites = new Writes[Enum[_]] {
    def writes(e: Enum[_]) = JsString(e.toString)
  }

  implicit val sex = enumReads(Sex.valueOf)

Also, upgrade to scala 2.11 or later to avoid the limitation of 22 fields in case class. For more info see here: How to get around the Scala case class limit of 22 fields?

I found this using google, and this worked greatly for me

// https://mvnrepository.com/artifact/com.chuusai/shapeless_2.11
libraryDependencies += "com.chuusai" % "shapeless_2.11" % "2.3.2"

// https://mvnrepository.com/artifact/org.julienrf/play-json-derived-codecs_2.11
libraryDependencies += "org.julienrf" % "play-json-derived-codecs_2.11" % "3.2"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM