您的位置:首页 > 编程语言 > Java开发

Protobuf 序列化和反序列化源码分析

2017-11-24 14:07 701 查看
假设大家对protobuf有一些基础,没有用过也没有关系

这里使用protobuf 3.5.0

编写proto文件

syntax = "proto3";

package tutorial;

option java_package = "com.spy.test.protobuf.model";
option java_outer_classname = "UserV3Proto";

// User domain comment
/* user domain comment*/
message User{
int64 user_id = 1;
string user_code = 2;
string user_name =3;
string  email =4;
int32 age = 5;
repeated string roles = 6;
map<string, string> address=7;
}


生成java类文件

protoc userV3.proto --java_out=./


编写序列化和反序列化单元测试

UserV3Proto.User user = UserV3Proto.User.newBuilder()
.setUserId(2L)
.setUserCode("00001")
.setUserName("cc")
.setAge(20)
.addRoles("admin")
.addRoles("cc")
.putAddress("a", "1")
.putAddress("b", "2")
.build();

byte[] bytes = user.toByteArray();
log.debug("{}", bytes);
log.debug("{}", bytes.length);

// 反序列化
UserV3Proto.User user2 = UserV3Proto.User.parseFrom(bytes);

log.debug("{}", user2.toString());


序列化后的码流

[8, 2, 18, 5, 48, 48, 48, 48, 49, 26, 2, 99, 99, 40, 20, 50, 5, 97, 100, 109, 105, 110, 50, 2, 99, 99, 58, 6, 10, 1, 97, 18, 1, 49, 58, 6, 10, 1, 98, 18, 1, 50]


下面就对这些码流进行分析,逐步拆解到每个字段

.toByteArray()源码分析





写int





通过上面的流程,发现写一个
TAG
,这个值是字段序号(
fieldNumber
)左移3位,再
上字段类型,得值8,再将值2输出,即:

user_id:   8, 2,


写String

以user_code为例:







同样,先写了一个
TAG
,其值为(2<<3|2)=18,然后输出string,即:

user_code:    18, 5, 48, 48, 48, 48, 49,


写Array

这里以role为例



其实这里的数组role,就是循环输出了String,这里不做过多说明,即:

role:      50, 5, 97, 100, 109, 105, 110,


role:      50, 2, 99, 99,


写Map

这里以address为例



这里开始序列化map字段





对map中每项进行输出



先输出TAG,58(自己计算,同上)



这里开始输出map中的具体内容



先输出了key和value的序列化总大小,6



将key和value内容序列化输出,
类型索引(key或value)大小+长度大小+具体内容


即:

-
address  58, 6, 10, 1, 97, 18, 1, 49,


-
address  58, 6, 10, 1, 98, 18, 1, 50


总结:

-
user_id:         8, 2,


-
user_code:   18, 5, 48, 48, 48, 48, 49,


-
user_name:   26, 2, 99, 99,


-
age:             40, 20,


-
role:            50, 5, 97, 100, 109, 105, 110,


-
role:        50, 2, 99, 99,


-
address:         58, 6, 10, 1, 97, 18, 1, 49,


-
address:     58, 6, 10, 1, 98, 18, 1, 50


.parseForm()源码分析







通过上述截图,可以直观看到根据
TAG
即可识别到具体的那个
field
,然后赋值。

全篇完。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java