MessagePack の Java 版を Scala から使ってみた。
なんでこんなことをしたかというと
MessagePack for Scala は現状 Scala 2.10 には対応していないらしく
(java.lang.NoClassDefFoundError: scala/reflect/ClassManifestエラーが発生する)、
2.10 対応版フォークを使用する、
自分で公式リポジトリから clone してワークアラウンドコードを入れてみる、
など対応方法はあると思うけど、
MessagePack for Java を使ってみるとどんな感じになるかを試してみた。
今回は JSON ⇔ MessagePack の変換。
MessagePack to JSON
org.msgpack.type.Value.toString() が JSON フォーマットの文字列を返してくれるので
それを呼んで scala.util.parsing.json.JSON.parseFull() とかしてやればおしまい。
ただそれでは面白くないので愚直に書くとどうなるかやってみた。
こういうのを作って、
val value: org.msgpack.`type`.Value = ... // new MessagePack().read() とかで取得
val map = Value2JsonMap.createMap(value)
こんな感じで Map[String, Any] を作れるので、後は如何様にも。
Java だと if (value.isRawValue) value.asRawValue.getString とかやるところが
パターンマッチでまかなえて良い感じかも。
JSON to MessagePack
さっきの逆パターンの object を作る。
val map: Map[String, _] = ...
val value = JsonMap2Value.createValue(map)
こんな感じで org.msgpack.type.Value を作れるので、後は write するだけ。
(型のパターンは網羅が足りてないけど…)
JSON to MessagePack(別バージョン)
上記はMapに入っているもの全部を Value にするけど、
キーを指定して特定の値のみ選択したい場合。
こういうトレイトを作っておいて、これをミックスインして使う。
たとえばこんなJSONを処理したい場合、
{
    "id" : 1,
    "name" : "zaneli",
    "friend" : [{"id" : 2}, {"id" : 3}, {"id" : 4}],
    "address" : {
      "zipcode" : "xxx-yyyy",
      "city" : "ihatov"
    }
}
こうする。
case class UserFactory(map: Map[String, _]) extends KeyValueFactory {
  def createValue: Value = {
    mapValue(map,
      intKeyValue("id"),
      rawKeyValue("name"),
      (arrayKeyValue("friend") { value: Map[String, Any] => mapValue(value, intKeyValue("id")) }),
      mapKeyValue("address")(
        rawKeyValue("zipcode"),
        rawKeyValue("city")))
  }
}
…おや、元々のJSONとcreateValueメソッドの見た目が似ていて、けっこう個人的には見栄え良く感じた。
こうなるとarrayKeyValueのところももっと簡潔にならないかなぁ…。

Copyright© 2011-2021 Shunsuke Otani All Right Reserved .