こんにちは、chaltosです。
今回は、msgpack-javaのバージョンを0.6.Xから上げたいが0.6.Xと同じフォーマットでシリアライズしたい場合の対処についてです。
MessagePackとは何なのかといった部分は省略させていただきます。
ひとことで
0.8.5以降のバージョンでorg.msgpack.core.MessagePack.PackerConfig.withStr8FormatSupport(false)
しましょう。
str8
MessagePackは2013年に仕様が変わったようで、それまでRaw bytesだった文字列のtypeがStringに変わりました。
それに伴いシリアライズのフォーマットもfix raw, raw16, raw32からfixstr, str8, str16, str32に変わりました。
それぞれのフォーマットは以下のようになっています。
* Raw bytes ** fix raw +--------+========+ |101XXXXX| data | +--------+========+ ** raw16 +--------+--------+--------+========+ | 0xda |ZZZZZZZZ|ZZZZZZZZ| data | +--------+--------+--------+========+ ** raw32 +--------+--------+--------+--------+--------+========+ | 0xdb |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA| data | +--------+--------+--------+--------+--------+========+ * String ** fixstr +--------+========+ |101XXXXX| data | +--------+========+ ** str8 +--------+--------+========+ | 0xd9 |YYYYYYYY| data | +--------+--------+========+ ** str16 +--------+--------+--------+========+ | 0xda |ZZZZZZZZ|ZZZZZZZZ| data | +--------+--------+--------+========+ ** str32 +--------+--------+--------+--------+--------+========+ | 0xdb |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA| data | +--------+--------+--------+--------+--------+========+ # XXXXX is a 5-bit unsigned integer which represents N # YYYYYYYY is a 8-bit unsigned integer which represents N # ZZZZZZZZ_ZZZZZZZZ is a 16-bit big-endian unsigned integer which represents N # AAAAAAAA_AAAAAAAA_AAAAAAAA_AAAAAAAA is a 32-bit big-endian unsigned integer which represents N # N is the length of data
だいたい同じなんですが、データサイズが32 ~ 255バイトの場合はシリアライズした結果が異なってしまいます。
scala> import org.msgpack.MessagePack import org.msgpack.MessagePack scala> val mp = new MessagePack mp: org.msgpack.MessagePack = org.msgpack.MessagePack@33d4ae0c scala> mp.write("a"*31) res0: Array[Byte] = Array(-65, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97) scala> mp.write("a"*32) res1: Array[Byte] = Array(-38, 0, 32, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97) scala> mp.write("a"*255) res2: Array[Byte] = Array(-38, 0, -1, 97, 97, 97, ..., 97) scala> mp.write("a"*256) res3: Array[Byte] = Array(-38, 1, 0, 97, 97, 97, ..., 97, 97)
scala> import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper scala> import org.msgpack.jackson.dataformat.MessagePackFactory import org.msgpack.jackson.dataformat.MessagePackFactory scala> import org.msgpack.core.MessagePack import org.msgpack.core.MessagePack scala> val config = new MessagePack.PackerConfig() config: org.msgpack.core.MessagePack.PackerConfig = org.msgpack.core.MessagePack$PackerConfig@164be01 scala> val objMapper = new ObjectMapper(new MessagePackFactory(config)) objMapper: com.fasterxml.jackson.databind.ObjectMapper = com.fasterxml.jackson.databind.ObjectMapper@6e5a587a scala> objMapper.writeValueAsBytes("a"*31) res0: Array[Byte] = Array(-65, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97) scala> objMapper.writeValueAsBytes("a"*32) res1: Array[Byte] = Array(-39, 32, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97) scala> objMapper.writeValueAsBytes("a"*255) res2: Array[Byte] = Array(-39, -1, 97, 97, 97, .., 97) scala> objMapper.writeValueAsBytes("a"*256) res3: Array[Byte] = Array(-38, 1, 0, 97, 97, 97, ..., 97, 97)
PackerConfig.withStr8FormatSupport
名前のとおり、str8フォーマットについての設定です。0.8.5で追加されました。
これの引数にfalseを渡すとstr8を使用しなくなります。
scala> val configForOldFormat = new MessagePack.PackerConfig().withStr8FormatSupport(false) configForOldFormat: org.msgpack.core.MessagePack.PackerConfig = org.msgpack.core.MessagePack$PackerConfig@164be00 scala> val objMapperForOldFormat = new ObjectMapper(new MessagePackFactory(configForOldFormat)) objMapperForOldFormat: com.fasterxml.jackson.databind.ObjectMapper = com.fasterxml.jackson.databind.ObjectMapper@3054da79 scala> objMapperForOldFormat.writeValueAsBytes("a"*32) res4: Array[Byte] = Array(-38, 0, 32, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97) scala> objMapperForOldFormat.writeValueAsBytes("a"*255) res5: Array[Byte] = Array(-38, 0, -1, 97, 97, 97, ..., 97)