Last active
November 16, 2018 08:57
-
-
Save xuwei-k/5e902a3875153cffa25f48ba7def4188 to your computer and use it in GitHub Desktop.
msgpack4zとmsgpack4z-circeのサンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scalaVersion := "2.12.6" | |
libraryDependencies ++= Seq( | |
"com.github.xuwei-k" %% "msgpack4z-circe" % "0.6.0", | |
"com.github.xuwei-k" %% "msgpack4z-native" % "0.3.5", // もしくは https://github.com/msgpack4z/msgpack4z-java 使うことも可能 | |
"io.circe" %% "circe-parser" % "0.9.3" | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example | |
import msgpack4z._ | |
import msgpack4z.CodecInstances.all._ | |
import scalaz.{\/-, -\/} | |
// テスト用case class | |
case class TestClass(foo: Int, bar: String) | |
object TestClass { | |
// json以外のサンプルはこっちでも同じようなことをしているので参照 | |
// https://github.com/msgpack4z/msgpack4z-core/blob/v0.3.9/src/test/scala/msgpack4z/CaseClassExample.scala | |
// シリアライズ部分と型クラス部分がライブラリ分かれてるので、このオブジェクトどこかで一度だけ作る処理が必要 | |
val factory = new PackerUnpackerFactory { | |
def packer = MsgOutBuffer.create() | |
def unpacker(bytes: Array[Byte]) = MsgInBuffer(bytes) | |
} | |
// msgpack の map としてシリアライズする場合 | |
// これも immutable で再利用可能なので、case classごとではなく、どこかで一回作れば良い | |
val mapCodecStringKey = CaseMapCodec.string(factory) | |
// arrayにシリアライズする場合はこっち使う | |
// mapかarrayか?は、読みやすさや、互換保ちやすさ、データ量などのトレードオフ | |
// https://github.com/msgpack4z/msgpack4z-core/blob/v0.3.9/src/main/scala/msgpack4z/CaseCodec.scala | |
// mapにシリアライズするがcase class の field のシリアライズ時の key を Int にしてデータ量を少しでも節約したい場合はこっち | |
val mapCodecIntKey = CaseMapCodec.int(factory) | |
// シリアライズ、デシリアライズのための型クラスのインスタンス生成 | |
// | |
// マクロなどで自動でcase classのfield名取得する機能はないので、 | |
// mapにシリアライズする場合のkeyはここで明示的に指定しないといけない | |
implicit val instance: MsgpackCodec[TestClass] = | |
mapCodecStringKey.codec(TestClass.apply _, TestClass.unapply _)("foo", "bar") | |
} | |
object Example { | |
def main(args: Array[String]): Unit = { | |
val value1 = TestClass(42, "abcdef") | |
// バイナリ生成(case classからmsgpackへのシリアライズ) | |
val bytes = MsgpackCodec[TestClass].toBytes(value1, MsgOutBuffer.create()) | |
// デシリアライズは失敗しうるので scalaz の \/ で返ってくる | |
val result = MsgpackCodec[TestClass].unpackAndClose(MsgInBuffer(bytes)) | |
result match { | |
case \/-(value2) => | |
// デシリアライズ成功 | |
println(value2) | |
assert(value1 == value2) | |
case -\/(error) => | |
// デシリアライズ失敗 | |
throw error | |
} | |
// ここまでmsgpack4z自体で主にcase classをシリアライズ、デシリアライズする場合の使い方で、 | |
// ここからmsgpack4z-circe関連 | |
// msgpack4z-circe以外のjson相互変換関連の、msgpack4z-argonaut や msgpack4z-play も、ほぼ同じ使い方 | |
// json <=> msgpack 変換のためのオブジェクト生成。 | |
// jsonとmsgpackには細かいところでインピーダンスミスマッチ?的なものがあるので、 | |
// オプションで、(NaNやInfinityや、"String以外のKey" などを)どう変換するか?を指定可能 | |
val jsonCodec = CirceMsgpack.jsonCodec(CirceUnpackOptions.default) | |
// msgpackのbyte列から、circeのJsonのオブジェクトに変換 | |
println(jsonCodec.unpackAndClose(MsgInBuffer(bytes))) | |
// circeのjsonを生成(以下の1行はcirce自体の使い方でmsgpack関係ない) | |
val Right(json) = io.circe.parser.parse(""" { "foo" : 42 , "bar" : "abcdef" } """) | |
// circeのjsonから、msgpackのbyte列に変換 | |
assert(java.util.Arrays.equals(jsonCodec.toBytes(json, MsgOutBuffer.create()), bytes)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment