Scala on Android で play-json を使う方法
AndroidでJSONを扱う場合、デフォルトのorg.jsonがありますがnullを直接扱ったりして微妙なライブラリです。
アプリ開発時のサーバーサイドとしてPlayFrameworkを使ってることもあり、使い慣れたplay-jsonを使いたいので使ってみました。
ちなみにObj->JSONはこんな感じにかけます
しかし普通に
resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/" libraryDependencies += "com.typesafe.play" %% "play-json" % "2.2.2-RC1"
こう書いて実行すると、Proguardが頑張り過ぎた場合に以下の例外が発生します
I/dalvikvm( 1681): Could not find method scala.collection.Set.hashCode, referenced from method play.api.libs.json.JsObject.hashCode W/dalvikvm( 1681): VFY: unable to resolve interface method 10596: Lscala/collection/Set;.hashCode ()I D/dalvikvm( 1681): VFY: replacing opcode 0x72 at 0x0004 W/dalvikvm( 1681): Exception Ljava/lang/NullPointerException; thrown while initializing Lcom/fasterxml/jackson/databind/cfg/MapperConfigBase; W/dalvikvm( 1681): Exception Ljava/lang/ExceptionInInitializerError; thrown while initializing Lplay/api/libs/json/JacksonJson$; W/System.err( 1681): java.lang.ExceptionInInitializerError W/System.err( 1681): at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:433) W/System.err( 1681): at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:364) W/System.err( 1681): at play.api.libs.json.JacksonJson$.<init>(JsValue.scala:462) W/System.err( 1681): at play.api.libs.json.JacksonJson$.<clinit>(JsValue.scala) W/System.err( 1681): at play.api.libs.json.Json$.stringify(Json.scala:48) W/System.err( 1681): at play.api.libs.json.JsValue$class.toString(JsValue.scala:77) W/System.err( 1681): at play.api.libs.json.JsObject.toString(JsValue.scala:164) W/System.err( 1681): at com.kohachori.example.MessageReceivingService.com$kohachori$example$MessageReceivingService$$update$1(MessageReceivingService.scala:80) W/System.err( 1681): at com.kohachori.example.MessageReceivingService$$anonfun$onCreate$1$$anonfun$apply$mcV$sp$2.apply(MessageReceivingService.scala:67) W/System.err( 1681): at com.kohachori.example.MessageReceivingService$$anonfun$onCreate$1$$anonfun$apply$mcV$sp$2.apply(MessageReceivingService.scala:63) W/System.err( 1681): at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) W/System.err( 1681): at scala.concurrent.impl.ExecutionContextImpl$$anon$3.exec(ExecutionContextImpl.scala:107) W/System.err( 1681): at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) W/System.err( 1681): at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.pollAndExecAll(ForkJoinPool.java:1253) W/System.err( 1681): at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1346) W/System.err( 1681): at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) W/System.err( 1681): at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) W/System.err( 1681): Caused by: java.lang.NullPointerException W/System.err( 1681): at java.lang.Enum$1.create(Enum.java:43) W/System.err( 1681): at java.lang.Enum$1.create(Enum.java:35) W/System.err( 1681): at libcore.util.BasicLruCache.get(BasicLruCache.java:54) W/System.err( 1681): at java.lang.Enum.getSharedConstants(Enum.java:209) W/System.err( 1681): at java.lang.Class.getEnumConstants(Class.java:705) W/System.err( 1681): at com.fasterxml.jackson.databind.cfg.MapperConfig.collectFeatureDefaults(MapperConfig.java:73) W/System.err( 1681): at com.fasterxml.jackson.databind.cfg.MapperConfigBase.<clinit>(MapperConfigBase.java:28) W/System.err( 1681): ... 17 more
この場合はProguardが頑張りすぎないように以下の2行を追加すればplay-jsonが動くようになります
"-keep class com.fasterxml.jackson.databind.** { *; }", "-keep interface com.fasterxml.jackson.databind.** { *; }"