MessagePack 是一种高效的二进制序列化格式。它支持多语言数据交换。相比JSON,它更紧凑,处理速度更快。
MessagePack 数据体积小。这意味着传输时占用带宽少,速度快。与JSON相比,MessagePack 支持更多原始数据类型。包括8位到64位整数、浮点数、时间戳和自定义扩展类型。
尽管有这些优势,MessagePack 已存在十多年。许多资深开发者甚至没听说过它。这表明它的流行度较低。
主要优势
在笔者看来,MessagePack 的最大优势是支持原始二进制数据。
设想一个场景:你需要通过HTTP接口上传文件或图片数据。
通常有两种解决方案:
- 第一,在请求体中直接放置二进制数据。
- 第二,使用
multipart/form-data作为传参协议。
如果还需要传递其他参数呢?按规范只能选择第二种方式。但如果你需要结构化的参数,multipart/form-data并不方便。虽然一些Web框架可以让其表现接近JSON,但处理流程不同。
这时,MessagePack 是个不错的选择。它允许你在请求体中包含类似JSON的数据,同时支持二进制数据。
使用方法
在 Rust 中,可以通过以下依赖使用:
[dependencies]
rmp-serde = "1.3.0"
假设有一个接口需要发送文本和二进制图片:
#[derive(Debug, PartialEq, Deserialize, Serialize)]
struct Message {
id: i32,
text: String,
image: Vec<u8>,
}
序列化代码如下:
fn main() {
let img = include_bytes!("../img.png");
let msg = Message {
id: 1,
text: "Hello, world!".to_string(),
image: img.to_vec(),
};
let mut buf = Vec::new();
msg.serialize(&mut Serializer::new(&mut buf)).unwrap();
println!("{:?}", buf);
}
当传输 MessagePack 数据时,请求头 Content-Type 可以是:
application/msgpackapplication/x-msgpackapplication/*+msgpack
Web 框架中的应用
如果你使用 Axum 开发Rust项目,可以添加这个crate:
cargo add axum-msgpack
使用非常简单:
async fn post_handler(MsgPack(msg): MsgPack<Message>) -> Html<String> {
let img = msg.image;
// 更多操作
"OK"
}
返回 MessagePack 数据也很容易:
async fn get_handler() -> MsgPack<Message> {
let img = include_bytes!("../img.png");
let msg = Message {
id: 1,
text: "Hello, world!".to_string(),
image: img.to_vec(),
};
MsgPack(msg)
}
支持程度
由于 MessagePack 实现简单,几乎所有主流编程语言都支持它。详情可参考 这里。
例如,在 JavaScript/TypeScript 中调用:
import { deepStrictEqual } from "assert";
import { encode, decode } from "@msgpack/msgpack";
const object = {
id: 1,
text: "Hello, world!",
image: Uint8Array.from([1, 2, 3]),
};
const encoded: Uint8Array = encode(object);
// encoded 就可以放到 http body 里传输到后端。
deepStrictEqual(decode(encoded), object);