MessagePack for Java を Scala から実行する
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のところももっと簡潔にならないかなぁ…。