Scalaといっしょ

ScalaでAndroidとiOSとPlayFrameworkを書いてます。

Scala on Android で play-json を使う方法

AndroidJSONを扱う場合、デフォルトの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.** { *; }"