Google Groups

[2.0.2-scala] ParsingException: Unable to find a case accessor for [case class with nested case class]


Jxtps Aug 8, 2012 2:08 PM
Posted in group: play-framework
I'm running into a problem deserializing nested case classes with Jerkson in Play.
case class Inner(foo: String, bar: Int)
case class Outer(hello: String, world: Inner)

object Application extends Controller {

  def index = Action {

    Logger.info("--------")
    val o = Outer("adam", Inner("eve", 4))
    Logger.info(o.toString)
    val oJson = com.codahale.jerkson.Json.generate(o)
    Logger.info(oJson)
    val o2 = com.codahale.jerkson.Json.parse[Outer](oJson)
    Logger.info(o2.toString)
    val o2Json = com.codahale.jerkson.Json.generate(o2)
    Logger.info(o2Json)
    Logger.info("--------")
 

    Ok("ok")

  }
}
 The bolded red line causes an exception:
 
2012-08-08 13:28:13,293  INFO  application - --------
2012-08-08 13:28:13,295  INFO  application - Outer(adam,Inner(eve,4))
2012-08-08 13:28:13,297  INFO  application - {"hello":"adam","world":{"foo":"eve","bar":4}}
2012-08-08 13:28:13,326  ERROR  application -
! @6ba4i1pig - Internal server error, for request [GET /] ->
play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[ParsingException: Unable to find a case access
or for controllers.Outer]]
        at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:134) [play_2.9.1.jar:2.0.2]
        at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:115) [play_2.9.1.jar:2.0.2]
        at akka.actor.Actor$class.apply(Actor.scala:318) [akka-actor.jar:2.0.2]
        at play.core.ActionInvoker.apply(Invoker.scala:113) [play_2.9.1.jar:2.0.2]
        at akka.actor.ActorCell.invoke(ActorCell.scala:626) [akka-actor.jar:2.0.2]
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:197) [akka-actor.jar:2.0.2]
        at akka.dispatch.Mailbox.run(Mailbox.scala:179) [akka-actor.jar:2.0.2]
        at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:516) [akka-acto
r.jar:2.0.2]
        at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259) [akka-actor.jar:2.0.2]
        at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975) [akka-actor.jar:2.0.2]
        at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1479) [akka-actor.jar:2.0.2]
        at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104) [akka-actor.jar:2.0.2]
Caused by: com.codahale.jerkson.ParsingException: Unable to find a case accessor for controllers.Outer
        at com.codahale.jerkson.ParsingException$.apply(ParsingException.scala:17) ~[jerkson_2.9.1.jar:na]
        at com.codahale.jerkson.Parser$class.parse(Parser.scala:86) ~[jerkson_2.9.1.jar:na]
        at com.codahale.jerkson.Json$.parse(Json.scala:6) ~[jerkson_2.9.1.jar:na]
        at com.codahale.jerkson.Parser$class.parse(Parser.scala:14) ~[jerkson_2.9.1.jar:na]
        at com.codahale.jerkson.Json$.parse(Json.scala:6) ~[jerkson_2.9.1.jar:na]
        at controllers.Application$$anonfun$index$1.apply(Application.scala:24) ~[classes/:2.0.2]
        at controllers.Application$$anonfun$index$1.apply(Application.scala:18) ~[classes/:2.0.2]
        at play.api.mvc.Action$$anonfun$apply$4.apply(Action.scala:204) ~[play_2.9.1.jar:2.0.2]
        at play.api.mvc.Action$$anonfun$apply$4.apply(Action.scala:204) ~[play_2.9.1.jar:2.0.2]
        at play.api.mvc.Action$$anon$1.apply(Action.scala:170) ~[play_2.9.1.jar:2.0.2]
        at play.core.ActionInvoker$$anonfun$receive$1$$anonfun$6.apply(Invoker.scala:126) ~[play_2.9.1.jar:2.0.2]
        at play.core.ActionInvoker$$anonfun$receive$1$$anonfun$6.apply(Invoker.scala:126) ~[play_2.9.1.jar:2.0.2]
        at play.utils.Threads$.withContextClassLoader(Threads.scala:17) ~[play_2.9.1.jar:2.0.2]
        at play.core.ActionInvoker$$anonfun$receive$1.apply(Invoker.scala:125) [play_2.9.1.jar:2.0.2]
        ... 11 common frames omitted
Caused by: org.codehaus.jackson.map.JsonMappingException: Unable to find a case accessor for controllers.Outer
        at com.codahale.jerkson.deser.CaseClassDeserializer$$anonfun$4.apply(CaseClassDeserializer.scala:39) ~[jerkson_2.9.1.jar:na]
        at com.codahale.jerkson.deser.CaseClassDeserializer$$anonfun$4.apply(CaseClassDeserializer.scala:39) ~[jerkson_2.9.1.jar:na]
        at scala.Option.getOrElse(Option.scala:108) ~[scala-library.jar:0.11.3]
        at com.codahale.jerkson.deser.CaseClassDeserializer.<init>(CaseClassDeserializer.scala:39) ~[jerkson_2.9.1.jar:na]
        at com.codahale.jerkson.deser.ScalaDeserializers.findBeanDeserializer(ScalaDeserializers.scala:94) ~[jerkson_2.9.1.jar:na]
        at org.codehaus.jackson.map.deser.BeanDeserializerFactory._findCustomBeanDeserializer(BeanDeserializerFactory.java:482) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:599) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider._createDeserializer(StdDeserializerProvider.java:401)~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCache2(StdDeserializerProvider.java:310) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider._createAndCacheValueDeserializer(StdDeserializerProvider.java:290) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider.findValueDeserializer(StdDeserializerProvider.java:159) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.deser.StdDeserializerProvider.findTypedValueDeserializer(StdDeserializerProvider.java:180) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.ObjectMapper._findRootDeserializer(ObjectMapper.java:2829) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2699) ~[jackson-mapper-asl.jar:1.9.7]
        at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1315) ~[jackson-mapper-asl.jar:1.9.7]
        at com.codahale.jerkson.Parser$class.parse(Parser.scala:83) ~[jerkson_2.9.1.jar:na]
        ... 23 common frames omitted
There's been some chatter in the past about Play and Jerkson. See:
 
Has anyone else run into this problem and found a solution?
 
Note that "simple" case classes work, i.e. case class Simple(a:String, b:Int) serialize & deserialize fine.
 
I don't know the innards of Java/Scala well enough to know if this is an independent Jerkson, or a Jerkson-Play combination issue.
 
The exception stems from https://github.com/codahale/jerkson/blob/master/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala#L36 - it seems like the CaseClassDeserializer doesn't find the correct constructor, but there's probably more to it than that.