This code works:
import net.liftweb.json.{DefaultFormats, parse}
object JsonTest {
def main(args: Array[String]): Unit = {
implicit val formats = DefaultFormats // Brings in default date formats etc.
case class RawObject(filters: List[ChunkObject])
case class ChunkObject(name: String)
val json = parse("""{"filters": []}""").extract[RawObject]
println(json)
}
}
It prints :
RawObject(List())
This same code within a class does not:
import net.liftweb.json.{DefaultFormats, parse}
class JsonTest2 {
def fct(): Unit = {
implicit val formats = DefaultFormats // Brings in default date formats etc.
case class RawObject(filters: List[ChunkObject])
case class ChunkObject(name: String)
val json = parse("""{"filters": []}""").extract[RawObject]
println(json)
}
}
object JsonTest2 {
def main(args: Array[String]): Unit = {
val jt = new JsonTest2
jt.fct()
}
}
Error:
Exception in thread "main" net.liftweb.json.MappingException: Parsed JSON values do not match with class constructor
args=List()
arg types=scala.collection.immutable.Nil$
constructor=public JsonTest2$RawObject$1(JsonTest2,scala.collection.immutable.List)
at net.liftweb.json.Meta$.fail(Meta.scala:227)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:274)
at net.liftweb.json.Extraction$.newInstance$1(Extraction.scala:308)
at net.liftweb.json.Extraction$.build$1(Extraction.scala:379)
at net.liftweb.json.Extraction$.extract0(Extraction.scala:444)
at net.liftweb.json.Extraction$.extract0(Extraction.scala:206)
at net.liftweb.json.Extraction$.extract(Extraction.scala:43)
at net.liftweb.json.JsonAST$JValue.extract(JsonAST.scala:703)
at JsonTest2.fct(JsonTest2.scala:9)
at JsonTest2$.main(JsonTest2.scala:17)
at JsonTest2.main(JsonTest2.scala)
Caused by: java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at net.liftweb.json.Extraction$.instantiate$1(Extraction.scala:265)
... 9 more
What did I miss?
PS: with a simple json (only a field with a string value so without a List inside) it works in both Object and Class
EDIT: I think it is related to the case class definition inside the function but i do not understand why.
From the look of the error messages it seems that the constructor for RawObject
takes an additional argument that liftweb is not expecting:
constructor=public JsonTest2$RawObject$1(JsonTest2,scala.collection.immutable.List)
RawObject
is a nested type, and in Scala nested types are unique for each instance of the containing object. So RawObject
inside one instance of JsonTest2
is not the same type as RawObject
inside a different instance of JsonTest2
.
I am guessing that Scala places the instance of the containing type (JsonTest2
) in the nested type (RawObject
) so that it can determine the type at runtime. Hence that JsonTest2
argument to the constructor for RawObject
.
So moving RawObject
and ChunkObject
out of the JsonTest2
class will fix the problem. These can be placed in the companion object to keep things neat.