6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Android/ScalaでJSONパース - jackson-databind編

Last updated at Posted at 2014-02-22

ScalaのJSONライブラリにはこちらのスレッドによると、ざっと下の選択肢がある。多い...

  1. parsing.json.JSON - 標準ライブラリ
  2. spray-json
  3. Jerkson - JacksonのScala用ラッパ
  4. sjson
  5. lift-json
  6. json4s - lift-json系
  7. Argonaut - Scalaz系
  8. play-json
  9. Jackson - Javaライブラリ

今回は、とっつきやすそうで、pull型(Streaming)パースをサポートしていて、Java界で実績がありそうなJacksonを試すことにした。環境はsbt-androidで、とりあえずJSONをScalaのオブジェクトとして取得(データバインド)してみることにした。

1. 依存関係の追加

build.sbtに jackson-core, jackson-databind を追加。

libraryDependencies += "com.fasterxml.jackson.core" % "jackson-core" % "2.3.0"

libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % "2.3.0"

2. モデルクラスの定義

引数無しコンストラクタと、プロパティごとにset*系のメソッドを定義する。

package com.example.app1.model

class MyModel1(
  var prop1: String,
  var prop2: Int
) {
  def this() = { this(null, -1) }
  def setProp1(a: String) { this.prop1 = a }
  def setProp2(a: Int) { this.prop2 = a }
}

JSONの生成もする場合はget*系も定義をする(略)。

3. JSONの読み込み例

package com.example.app1
import com.fasterxml.jackson.databind.ObjectMapper
import com.example.app1.model.MyModel1

class Class1 {
  def method1 = {
    ...
    val json = """{"prop1": "value1", "prop2": 1234}"""
    val model1 = (new ObjectMapper).readValue(json, classOf[MyModel1])
    model1.prop1 // => "value1"
  }
}

4. proguardの設定

データバインドの際に使われるクラス名などをproguardの難読化の対象から外すため、proguard.cfgに下を追加する。

-keep class com.fasterxml.jackson.databind.** { *; }
-keepattributes *Annotation*,EnclosingMethod
-keep public class com.example.app1.model.** {
  public void set*(***);
  public *** get*();
}

1つめはjackson-databindのパッケージを、サブパッケージ含めて全て難読化対象外にするもの。
2つめはjacksonが使っているアノテーションとenclosing methodを難読化対象外にするもの。Javaではメソッドの中にローカルなクラスを定義できるらしく(enclosing method)、Jacksonがこれを使っている。jackson-databindのソースgetEnclosingMethodでgit grepすると、この機能(enclosing method)が使われているのが分かる。
3つめはMyModel1などモデルクラスとそのget系, set系メソッドを難読化対象外にするもの。

5. apk生成

apkファイルを生成する際、 compile:dx フェーズでtrouble writing output: excess write of ...というエラーが出た。

sbt> apk
...
trouble writing output: excess write of 16
[trace] Stack trace suppressed: run last App2/compile:dx for the full output.
[error] (App2/compile:dx) Nonzero exit value: 2
[error] Total time: 17 s, completed Feb 22, 2014 10:06:32 AM

project/Build.scala でanalysisBudgetを512から4096に増やすと解消した。こちらによると、Scalaコンパイラがソースコードの到達可能性・条件網羅性の検査(?)に最大どれくらい時間をかけるかというパラメータらしい...

object AndroidBuild extends Build {
  ...
  val globalSettings = Seq (
    ...
    initialize ~= { _ =>
      sys.props("scalac.patmat.analysisBudget") = "4096"
    }
  )

  lazy val main = AndroidProject (
    ...
    settings = globalSettings
  )
}

6. 動作確認

こちらのテスト用MainActivityを書いて実行したところ、無事に"value1"が表示された。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?