问题描述
在 Scala 2.11 中,我们允许在一个 case 类中有超过 22 个字段,对吧??
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]
上面是一个 case 类,它有 22 个字段,格式为 play-json,现在当我编译时,我得到这个错误:
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]
案例类 Phone 和 Foo 各有两个字段.
And the case class Phone and Foo, each have two fields each.
那么,为什么我真的面临这个问题,它没有超过 22 个字段的限制,或者我做错了什么,我在 scala 2.11.5/2.11.1 中尝试过 - 播放-json 2.3
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
更新:根据 James 和 Phadej 的回答
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)))
推荐答案
您可以拆分您的 Reads
定义:
You can split your Reads
definition:
val fields1to10: Reads[(A,B,C,D,E,F,G,H,I,J)] = ???
val fields11to20 = ???
val fields21to30 = ???
implicit val hugeCaseClassReads: Reads[HugeCaseClass] = (
fields1to10 and fields11to20 and fields21to30
) { a, b, c => createHugeCaseClassFromThreeTuples(a, b, c) }
函数式语法"对超过 22 个字段不起作用的原因是因为中间类最多只定义了 22 个:FunctionalBuilder
完整写出来的小例子,它看起来像:
Fully written out for small example it would look like:
import play.api.libs.json._
import play.api.libs.functional.syntax._
// Let's pretend this is huge:
case class Huge(a: Int, b: String, c: Boolean, d: List[Int])
val fields1to2: Reads[(Int, String)] = (
(__ "a").read[Int] and
(__ "b").read[String]
).tupled
val fields3to4: Reads[(Boolean, List[Int])] = (
(__ "c").read[Boolean] and
(__ "d").read[List[Int]]
).tupled
implicit val hugeCaseClassReads: Reads[Huge] = (
fields1to2 and fields3to4
) {
case ((a, b), (c, d)) =>
Huge(a, b, c, d)
}
以及tryint验证null
的结果:
And the result of tryint to validate null
:
scala> JsNull.validate[Huge]
res6: play.api.libs.json.JsResult[Huge] = JsError(
List(
(/b,List(ValidationError(error.path.missing,WrappedArray()))),
(/d,List(ValidationError(error.path.missing,WrappedArray()))),
(/c,List(ValidationError(error.path.missing,WrappedArray()))),
(/a,List(ValidationError(error.path.missing,WrappedArray())))))
如您所见,所有字段均已尝试.
As you can see, all fields are tried.
或者您可以使用更多 CanBuildNN
类来扩展游戏:https://github.com/playframework/playframework/blob/2.3.6/framework/src/play-功能/src/main/scala/play/api/libs/functional/Products.scala
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.scala
但我建议您将 SomeResponse
类中的字段分组,例如地址相关等.并编写 Reads
和 Writes
实例手动,如果 JSON 结构是扁平的且无法更改.
Yet I'd advice you to group fields in the SomeResponse
class, for example address related etc. And write Reads
and Writes
instances by hand, if the JSON structure is flat and cannot be changed.
这篇关于Scala 案例有 22 个字段,但在 Scala 2.11.5 中存在 play-json 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!