2013 年接受的答案提出了一个不再维护的库。 StackOverflow 上有很多类似的问题,但我真的找不到符合以下条件的好答案:
- 序列化/反序列化应该很快
- 通过网络进行高性能数据交换,您只需编码所需的尽可能多的元数据
- 支持模式演变,以便更改序列化对象(例如:
case class)不会破坏过去的反序列化
我建议不要使用低级 JDK SerDes(如 ByteArrayOutputStream 和 ByteArrayInputStream)。支持模式演变变得很痛苦,并且很难使其与外部服务(例如:Thrift)一起使用,因为您无法控制发回的数据是否使用相同类型的流。
有些人使用 JSON 规范,使用像 json4s 这样的库,但它不适合分布式计算消息传输。它将数据编组为 JSON 字符串,因此速度较慢且存储效率低,因为它将使用 8 位来存储字符串中的每个字符。
我强烈推荐使用MessagePack 二进制序列化格式。我建议阅读规范以了解编码细节。它具有多种不同语言的实现,这是我为 Scala case class 编写的通用示例,您可以将其复制粘贴到您的代码中。
import java.nio.ByteBuffer
import java.util.concurrent.TimeUnit
import org.msgpack.core.MessagePack
case class Data(message: String, number: Long, timeUnit: TimeUnit, price: Long)
object Data extends App {
def serialize(data: Data): ByteBuffer = {
val packer = MessagePack.newDefaultBufferPacker
packer
.packString(data.message)
.packLong(data.number)
.packString(data.timeUnit.toString)
.packLong(data.price)
packer.close()
ByteBuffer.wrap(packer.toByteArray)
}
def deserialize(data: ByteBuffer): Data = {
val unpacker = MessagePack.newDefaultUnpacker(convertDataToByteArray(data))
val newdata = Data.apply(
message = unpacker.unpackString(),
number = unpacker.unpackLong(),
timeUnit = TimeUnit.valueOf(unpacker.unpackString()),
price = unpacker.unpackLong()
)
unpacker.close()
newdata
}
def convertDataToByteArray(data: ByteBuffer): Array[Byte] = {
val buffer = Array.ofDim[Byte](data.remaining())
data.duplicate().get(buffer)
buffer
}
println(deserialize(serialize(Data("Hello world!", 1L, TimeUnit.DAYS, 3L))))
}
它将打印:
Data(Hello world!,1,DAYS,3)