With Scala 2.11, we are allowed to have more then 22 fields in a case class right??
case class SomeResponse(
var compositeKey: String,
var id1: String,
var id2: String,
var firstName: String,
var lastName: String,
var email: String,
var email2: String,
var birth: Long,
var gender: String,
var phone: Phone,
var city: String,
var zip: String,
var carriage: Boolean,
var carriage2: Boolean,
var fooLong: Long,
var fooLong2: Long,
var suspended: Boolean,
var foo: Foo,
var address: String,
var suite: String,
var state: String,
var instructions: String)
implicit val formatSomeResponse = Json.format[SomeResponse]
Well the above is a case class which has exactly 22 fields with the play-json format, now when I compile, I get this error:
SomeFile.scala:126: value apply is not a member of play.api.libs.functional.FunctionalBuilder[play.api.libs.json.OFormat]#CanBuild22[String,String,String,String,String,String,String,Long,String,com.Phone,String,String,Boolean,Boolean,Long,Long,Boolean,com.Foo,String,String,String,String]
And the case class Phone and Foo, each have two fields each.
So, why am I actually facing the issue, it doesn't cross the 22 fields limit or is there something else I did wrong, and I tried it in scala 2.11.5/2.11.1 - play-json 2.3
Update: Based on answers by James and Phadej
val someResponseFirstFormat: OFormat[(String, String, String, String, String, String, String, Long, String, Phone, String)] =
((__ \ "compositeKey").format[String] and
(__ \ "id1").format[String] and
(__ \ "id2").format[String] and
(__ \ "firstName").format[String] and
(__ \ "lastName").format[String] and
(__ \ "email").format[String] and
(__ \ "email2").format[String] and
(__ \ "birth").format[Long] and
(__ \ "gender").format[String] and
(__ \ "phone").format[Phone] and
(__ \ "city").format[String]).tupled
val someResponseSecondFormat: OFormat[(String, Boolean, Boolean, Long, Long, Boolean, Foo, String, String, String, String)] =
((__ \ "zip").format[String] and
(__ \ "carriage").format[Boolean] and
(__ \ "carriage2").format[Boolean] and
(__ \ "fooLong").format[Long] and
(__ \ "fooLong2").format[Long] and
(__ \ "suspended").format[Boolean] and
(__ \ "foo").format[Foo] and
(__ \ "address").format[String] and
(__ \ "suite").format[String] and
(__ \ "country").format[String] and
(__ \ "instructions").format[String]).tupled
implicit val formatSome: Format[SomeResponse] = (
someResponseFirstFormat and someResponseSecondFormat
).apply({
case ((compositeKey, id1, id2, firstName, lastName, email, email2, birth, gender, phone, city),
(zip, carriage, carriage2, created, updated, suspended, foo, address, suite, country, instructions)) =>
SomeResponse(compositeKey, id1, id2, firstName, lastName, email, email2, birth, gender, phone, city, zip, carriage, carriage2, created, updated, suspended, location, address, suite, country, instructions)
}, huge => ((huge.compositeKey, huge.id1, huge.id2, huge.firstName, huge.lastName, huge.email, huge.email2, huge.birth, huge.gender, huge.phone, huge.city),
(huge.zip, huge.carriage, huge.carriage2, huge.created, huge.updated, huge.suspended, huge.foo, huge.address, huge.suite, huge.country, huge.instructions)))
To make the example above compile, I had to make the type explicit:
You can split your
Reads
definition:The reason why "functional syntax" doesn't work for more than 22 fields is because there are intermediate classes defined only up to 22: FunctionalBuilder
Fully written out for small example it would look like:
And the result of tryint to validate
null
:As you can see, all fields are tried.
Or you could extend play with even more
CanBuildNN
classes: https://github.com/playframework/playframework/blob/2.3.6/framework/src/play-functional/src/main/scala/play/api/libs/functional/Products.scalaYet I'd advice you to group fields in the
SomeResponse
class, for example address related etc. And writeReads
andWrites
instances by hand, if the JSON structure is flat and cannot be changed.