Protobuf 编码及序列化的记录

本文详细介绍了Google的Protocol Buffers(Protobuf)的编码和序列化过程,包括protobuf的简单介绍、如何确定字段是否需要序列化、序列化与反序列化的实现原理,以及protobuf序列化格式和字段信息的保存方式。通过对protobuf源码的分析,揭示了protobuf如何实现向前和向后兼容,以及字段设置与序列化的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     工作中用到了protobuf,然后之前在面试的时候面试官就问了一个问题,如果将int32类型的字段的值设置为0,那还会将该值进行序列化吗?当时是懵了的,因为自己还没有研究这部分。当时给的结果是不会,猜测protobuf中int32的默认值是0,既然默认值是0的,那应该就不会进行序列化了。

      那次面试之后就觉得自己应该了解一下这部分了,结果这两天了解完之后,发现自己猜错了。好记性不如烂笔头,也顺便记录下这两天了解到的吧。如果觉得写得有点乱了,请原谅。这里使用的是protobuf版本是2.6.1。

1. protobuf简单介绍

       即Protocol Buffer,是一个灵活的、高效的、自动化的用于对结构化数据进行序列化的协议,与XML相比,Protocol buffers序列化后的码流更小、速度更快、操作更简单,还是支持向前兼容和向后兼容的。

      protobuf中使用了反射机制,可以根据字段的名字直接得到字段的值,更深入的我还没有了解,所以需要大家去百度下了。后面了解完的话,我会再写篇博客介绍的。

      一个简单的proto文件内容如下:

message PbInfo
{
    optional uint64 uid     = 1;
    optional uint32 time    = 2;
    optional uint32 type    = 3;
    required string account = 5;    
    repeated string key     = 7;   
}

         可以看到每个字段都是由字段规则、字段类型、字段值、字段的编号组成,字段的规则有三种:optional fields(可选字段)、required fields(必须字段)、repeated fields(可重复字段),message内每个字段的编号都要是唯一的。

         那protobuf是怎么做到向前及向后兼容的呢?靠的就是这个字段的编号,在反序列化的时候,protobuf会从输入流中读取出字段编号,然后再设置message中对应的值。如果读出来的字段编号是message中没有的,就直接忽略,如果message中有字段编号是输入流中没有的,则该字段不会被设置。所以即使通信的两端存在一方比另一方多出编号,也不会影响反序列化。但是如果两端同一编号的字段规则或者字段类型不一样,那就肯定会影响反序列化了。所以一般调整proto文件的时候,尽量选择加字段或者删字段,而不是修改字段编号或者字段类型。

2. protobuf怎么知道哪些字段需要序列化

     下面的代码,是上面的文件编译生成c文件的一部分。

inline bool PbInfo::has_uid() const {
  return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void PbInfo::set_has_uid() {
  _has_bits_[0] |= 0x00000001u;
}
inline void PbInfo::clear_has_uid() {
  _h
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值