MessagePack の Java 版を Scala から使ってみた。
(java.lang.NoClassDefFoundError: scala/reflect/ClassManifestエラーが発生する)、
2.10 対応版フォークを使用する、
自分で公式リポジトリから clone してワークアラウンドコードを入れてみる、
など対応方法はあると思うけど、
MessagePack for Java を使ってみるとどんな感じになるかを試してみた。
今回は JSON ⇔ MessagePack の変換。
なんでこんなことをしたかというと
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のところももっと簡潔にならないかなぁ…。