Protocol Buffers(簡稱:ProtoBuf)是一種開源跨平台的序列化資料結構的協定。其對於儲存資料或在網絡上進行通訊的程式是很有用的。這個方法包含一個介面描述語言,描述一些資料結構,並提供程式工具根據這些描述產生程式碼,這些代碼將用來生成或解析代表這些數據結構的位元組流。
ProtoBuf类似于json xml是一种网络数据交换的新格式。以下例子使用nodejs作为后端,原生html+js作为前端,使用protobufjs这个纯js库处理ProtoBuf。其中后端使用proto文件作为消息类,前端使用json对象作为消息类。
后端 Link to heading
const express = require('express')
const protobuf = require('protobufjs')
const path = require('path')
const app = express()
const port = 3000
const htmlPath = path.join(__dirname, './index.html')
const protoPath = path.join(__dirname, './awesome.proto')
const payload = {
name: 'lihua',
age: 28,
address: '上海市浦东新区纳贤路701号'
}
app.get('/', (req, res) => {
res.sendFile(htmlPath)
})
app.get('/api', async (req, res) => {
const root = await protobuf.load(protoPath)
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage")
const errMsg = AwesomeMessage.verify(payload);
if (errMsg) throw Error(errMsg);
const message = AwesomeMessage.create(payload);
const buffer = AwesomeMessage.encode(message).finish();
res.setHeader('content-type', 'application/x-protobuf')
res.send(buffer);
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
awesome.proto
package awesomepackage;
syntax = "proto3";
message AwesomeMessage {
string name = 1;
int32 age = 2;
string address = 3;
}
前端 Link to heading
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/protobufjs@7.2.3/dist/protobuf.min.js"></script>
<style>
span{
display: inline-block;
padding: 0px 8px;
}
</style>
</head>
<body>
<div>
<span id="name">name:</span>
<span id="age">age:</span>
<span id="address">address:</span>
</div>
<script>
const proto = {
"nested": {
"awesomepackage": {
"nested": {
"AwesomeMessage": {
"fields": {
"name": {
"type": "string",
"id": 1
},
"age": {
"type": "int32",
"id": 2
},
"address": {
"type": "string",
"id": 3
}
}
}
}
}
}
}
fetch('/api')
.then(res => res.arrayBuffer())
.then(buffer => {
const root = protobuf.Root.fromJSON(proto);
const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage")
const message = AwesomeMessage.decode(new Uint8Array(buffer))
const name = document.querySelector('#name')
const age = document.querySelector('#age')
const address = document.querySelector('#address')
name.innerHTML = `name: ${message.name}`
age.innerHTML = `age: ${message.age}`
address.innerHTML = `address: ${message.address}`
})
</script>
</body>
</html>