Lift Case Class Exceeding 22 Arguments

☆樱花仙子☆ 提交于 2019-12-06 12:18:56

问题


Using Lift, I'm trying to "extract" (get a case class representation of) my JSON.

val json: JValue = getJson()
case class BigObj(name: String, age: Int, ...)
json.extract[BigObj]

When using more than 22 arguments, I get a JVM run-time exception that case classes cannot exceed 22 arguments.

How can I work around this limit?


回答1:


As has been mentioned, you can't overcome that limit with a case class explicitly, however you can use the extract method without a case class. See this example, which I ran through REPL to verify:

scala> import net.liftweb.json._
import net.liftweb.json._

scala> implicit val formats = net.liftweb.json.DefaultFormats
formats: net.liftweb.json.DefaultFormats.type = net.liftweb.json.DefaultFormats$@734784c4

scala> val json = parse(""" {
     |           "v1": "Test1",
     |           "v2": "Test2",
     |           "v3": "Test3",
     |           "v4": "Test4",
     |           "v5": "Test5",
     |           "v6": "Test6",
     |           "v7": "Test7",
     |           "v8": "Test8",
     |           "v9": "Test9",
     |           "v10": "Test10",
     |           "v11": "Test11",
     |           "v12": "Test12",
     |           "v13": "Test13",
     |           "v14": "Test14",
     |           "v15": "Test15",
     |           "v16": "Test16",
     |           "v17": "Test17",
     |           "v18": "Test18",
     |           "v19": "Test19",
     |           "v20": "Test20",
     |           "v21": "Test21",
     |           "v22": "Test22",
     |           "v23": "Test23"
     | } """)
json: net.liftweb.json.JValue = JObject(List(JField(v1,JString(Test1)), JField(v2,JString(Test2)), JField(v3,JString(Test3)), JField(v4,JString(Test4)), JField(v5,JString(Test5)), JField(v6,JString(Test6)), JField(v7,JString(Test7)), JField(v8,JString(Test8)), JField(v9,JString(Test9)), JField(v10,JString(Test10)), JField(v11,JString(Test11)), JField(v12,JString(Test12)), JField(v13,JString(Test13)), JField(v14,JString(Test14)), JField(v15,JString(Test15)), JField(v16,JString(Test16)), JField(v17,JString(Test17)), JField(v18,JString(Test18)), JField(v19,JString(Test19)), JField(v20,JString(Test20)), JField(v21,JString(Test21)), JField(v22,JString(Test22)), JField(v23,JString(Test23))))

scala> class MyLargeArgClass(val v1:String, val v2:String, val v3:String, val v4:String, val v5:String, val v6:String, val v7:String, val v8:String, val v9:String, val v10:String, val v11:String, val v12:String, val v13:String, val v14:String, val v15:String, val v16:String, val v17:String, val v18:String, val v19:String, val v20:String, val v21:String, val v22:String, val v23:String) {
     | 
     |   override def toString = "MyLargeArgClass(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)".format(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
     | 
     | }
defined class MyLargeArgClass

scala> json.extract[MyLargeArgClass]
res0: MyLargeArgClass = MyLargeArgClass(Test1, Test2, Test3, Test4, Test5, Test6, Test7, Test8, Test9, Test10, Test11, Test12, Test13, Test14, Test15, Test16, Test17, Test18, Test19, Test20, Test21, Test22, Test23)

And then going back from the class to JSON

scala> Extraction.decompose(res0)
res1: net.liftweb.json.JValue = JObject(List(JField(v1,JString(Test1)), JField(v2,JString(Test2)), JField(v3,JString(Test3)), JField(v4,JString(Test4)), JField(v5,JString(Test5)), JField(v6,JString(Test6)), JField(v7,JString(Test7)), JField(v8,JString(Test8)), JField(v9,JString(Test9)), JField(v10,JString(Test10)), JField(v11,JString(Test11)), JField(v12,JString(Test12)), JField(v13,JString(Test13)), JField(v14,JString(Test14)), JField(v15,JString(Test15)), JField(v16,JString(Test16)), JField(v17,JString(Test17)), JField(v18,JString(Test18)), JField(v19,JString(Test19)), JField(v20,JString(Test20)), JField(v21,JString(Test21)), JField(v22,JString(Test22)), JField(v23,JString(Test23))))

Overriding the toString wasn't necessary - I just needed to see what data was being added. However, since this is not a case class, you will lose some of the automatic methods that come with it. So, if you need to put it in an HTTP Session, you may want to implement Serializable. For pattern matching, you'd need an unapply method, etc...

You should also be able to use formats to specify your own additional rules for parsing and extracting data from your JSON.




回答2:


There's no getting around the 22-limit with case classes, tuples, etc. It's a limitation of Scala. However, if you can deal with having a regular class, then you can certainly do this. You just won't get the matching, equals, hashCode, etc. for free.



来源:https://stackoverflow.com/questions/18877851/lift-case-class-exceeding-22-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!