从json到protobuf,接口效率的提升

在express开发的前后端调用中,express作为服务端是不二之选,它有一些很好用的body解析器来解析传入数据;而作为请求发起方,axios是非常方便的,这是一个很好的选择,它可以传输多种类型的数据给接收方。
通常我们用urlencoded和json传一些数据量小的信息是蛮不错的,但是如果数据量大的话,或者感觉编码效率低的话,可以考虑用blob或者arraybuffer,当然如果某些属性就是blob或者arraybuffer,直接传就好了,但是如果类似一些较大的json对象数组,类似数据库宽表的一页或者几页信息,真是占空间,自己设计转码还挺麻烦,有没有什么好的办法呢?
这里要推荐一下protobuf,protobuf 就是Protocol Buffer,它是一种由 Google 开发的二进制序列化格式和相关的技术,它用于高效地序列化和反序列化结构化数据,大名鼎鼎的gRPC里用的就是这个。当然在本文里,我不是让你放弃express+axios,彻底转向gRPC的怀抱,而是利用protobuf来提高我们接口的传输效率。
首先,需要定义下接口数据格式,用proto定义比json更为精准,每条数据的各属性类型顺序,如果支持一个请求里传输多条数据,只需要来一个repeated定义即可。

//dgiij.proto
package dgiijpackage;
syntax = "proto3";

message welcomeMessage {
	string id = 1;
	int64 timecount = 2;
	string url = 3;
}

message msgs
{
    repeated welcomeMessage msg = 1;
}

在原接口请求方和服务方简单增加两句,用于在数据发送前和收到后,进行转码和解码即可
下面是node客户端代码

//sender.js
const axios = require('axios');
var protobuf = require("protobufjs");
const root=protobuf.loadSync("dgiij.proto");
const dgiijMessage = root.lookupType("dgiijpackage.msgs");

let dataset=[{ "id": "dgiij","timecount":202407271054,"url":"https://blog.csdn.net/dgiij" },{ "id": "dgiij1","timecount":202407271134,"url":"https://blog.csdn.net/dgiij1" }];

var messageout = dgiijMessage.create({"msg":dataset});
var buffer = dgiijMessage.encode(messageout).finish();
 
axios.post('http://localhost:3000/sendmsg',buffer,{ headers: {'Content-Type': 'application/octet-stream'}}).then(res=>console.log(res.data))

axios.get('http://localhost:3000/getmsg',{responseType:'arraybuffer'}).then(res=>{
	let messagein = dgiijMessage.decode(res.data);
	console.log("解码数据为:");
	console.log(messagein.msg)
	messagein.msg.forEach(item=>{item.pasrelong=item.timecount.toNumber()})
	console.log("long类型转数字后数据为:");
	console.log(messagein.msg)
	})


下面是node服务端代码

//receiver.js
const protobuf = require("protobufjs");
const root=protobuf.loadSync("dgiij.proto");
const dgiijMessage = root.lookupType("dgiijpackage.msgs");

const express = require('express');
const app = express();

app.use("/", express.static("./"));

app.post('/sendmsg',express.raw(), (req, res)=> {
	let message = dgiijMessage.decode(req.body);
	console.log("解码数据为:");
	console.log(message.msg)
	message.msg.forEach(item=>{item.pasrelong=item.timecount.toNumber()})
	console.log("long类型转数字后数据为:");
	console.log(message.msg)
	res.json({"msg":"got"});
})

app.get('/getmsg', (req, res)=> {

let dataset=[{ "id": "dgiij","timecount":202407271054,"url":"https://blog.csdn.net/dgiij" },{ "id": "dgiij1","timecount":202407271134,"url":"https://blog.csdn.net/dgiij1" }];

var message = dgiijMessage.create({"msg":dataset});
var buffer = dgiijMessage.encode(message).finish();

res.set('Content-Type', 'arrarybuffer');
res.write(buffer);
res.end();
})


app.listen(3000, ()=> {
	console.log("Server is listening");
});

运行结果如下

在这里插入图片描述
在这里插入图片描述
下面这个是浏览器端测试网页

<html>
<head>
<script src="axios.min.js"></script>
<script src="protobuf.js"></script>
</head>
<body>
<div>protobuf test</div>
<script>
protobuf.load("./dgiij.proto").then(root=>{

const dgiijMessage = root.lookupType("dgiijpackage.msgs");

let dataset=[{ "id": "dgiij","timecount":202407271054,"url":"https://blog.csdn.net/dgiij" },{ "id": "dgiij1","timecount":202407271134,"url":"https://blog.csdn.net/dgiij1" }];
let messageout = dgiijMessage.create({"msg":dataset});
let buffer = dgiijMessage.encode(messageout).finish();
 
axios.post('http://localhost:3000/sendmsg',buffer,{ headers: {'Content-Type': 'application/octet-stream'}}).then(res=>console.log(res.data));

axios.get('http://localhost:3000/getmsg',{responseType:'arraybuffer'}).then(res=>{
	let messagein = dgiijMessage.decode(new Uint8Array(res.data));
	console.log(messagein.msg)
	})
});
</script>
</body>
</html>

效果如下
在这里插入图片描述
提醒注意下:浏览器端调用发送数据跟后端没有区别,但是接收数据的话要将返回数据按Uint8Array来解码,否则会报错,另外解码后的long型数字也不用转换了。

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用第三方库,如protobuf-json-util来实现C++中JSONProtobuf的功能。个库提供了一些方便的函数和接口,可以帮助你在ProtobufJSON之间进行转换。 首先,你需要在你的C++项目中引入protobuf-json-util库。你可以在GitHub上找到该库的源代码并进行下载和安装。 然后,你需要定义你的Protobuf消息和相应的JSON格式。在Protobuf中,你可以使用.proto文件定义消息结构,在JSON中,你可以使用类似的结构来表示相同的数据。 接下来,你可以使用protobuf-json-util库提供的函数来实现JSONProtobuf的转换。你可以使用`ParseFromJsonString()`函数将JSON字符串解析为Protobuf消息对象,使用`SerializeToJsonString()`函数将Protobuf消息对象序列化为JSON字符串。 下面是一个简单的示例代码: ```cpp #include <iostream> #include <string> #include <protobuf-json-util/json_util.h> #include "your_protobuf_message.pb.h" int main() { // 定义一个Protobuf消息对象 YourProtobufMessage message; // 从JSON字符串解析Protobuf消息对象 std::string json = R"( { "field1": 123, "field2": "hello", "field3": true } )"; json_util::Status status = json_util::ParseFromJsonString(json, &message); if (!status.ok()) { std::cerr << "Failed to parse JSON: " << status.error_message() << std::endl; return 1; } // 将Protobuf消息对象序列化为JSON字符串 std::string serialized_json = json_util::SerializeToJsonString(message); std::cout << "Serialized JSON: " << serialized_json << std::endl; return 0; } ``` 请确保按照protobuf-json-util库的文档进行正确的安装和配置,并根据你的实际需求修改示例代码中的消息类型和字段名。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值