序列化和反序列化##

序列化和反序列化在平常工作中会大量使用,然而并不一定非常清楚它的概念。序列化和反序列化的选型却是系统设计或重构一个重要的环节,在分布式、大数据量系统设计里面更为显著。机器间的通信需要约定一个协议,序列化和反序列化是这个通信协议的一部分。

序列化:将对象或数据结构转为字节序列的过程。

反序列化:将序列化后生成的字节序列转为对象或数据结构的过程。

常用序列化和反序列化组件##

比较常见的序列化和反序列化组方式有XML、JSON和Protobuf等。XML标准化较早,基于XML的SOAP是一种应用广泛的结构化数据传递协议。JSON源于js,较之XML它更小、解析更快,而且同样具备可读性好的优点。而源于谷歌的protobuf现在在大型分布式系统广泛使用。

Protobuf##

Protobuf是谷歌推出的一款平台无关,语言无关,可扩展的序列化和反序列化技术。

字段规则

要使用Protobuf,首先需要定义.proto文件

如下proto2中:

message msg
{
required int32 a=1;
optional string b=2;
repeated string c=3;
}

其中:

  • message是消息定义的关键字。
  • required 表示这个字段必须的,必须在序列化的时候被赋值。
  • optional 代表这个字段是可选的,可以为0个或1个但不能大于1个。
  • repeated 则代表此字段可以被重复任意多次包括0次。类似C++ STL中的vector。
  • int32和string是字段的类型。后面是我们定义的字段名。
  • 最后的1,2,3则是代表每个字段的一个唯一的编号标签,在同一个消息里不可以重复。这些编号标签用与在消息二进制格式中标识你的字段,并且消息一旦定义就不能更改。需要说明的是标签在1到15范围的采用一个字节进行编码。所以通常将标签1到15用于频繁发生的消息字段。编号标签大小的范围是1到\(2^{29}-1\)。此外不能使用protobuf系统预留的编号标签(19000 -19999)。

而在proto3中,字段规则中去除了required和optional,增加singular。但是proto3仍兼容proto2

message msg
{
int32 a=1;
singular string b=2;
repeated string c=3;
}

其中,

  • singular:一个格式良好的消息应该有0个或者1个这种字段(但是不能超过1个)。
  • repeated
  • 在proto3中,repeated的标量域默认情况下使用packed。

一个较完整的.proto文件

syntax = "proto3";
message Article {
int32 article_id = 1;
singular string article_excerpt = 2;
repeated string article_picture = 3;
singular int32 article_pagecount = 4 [default = 0];
enum ArticleType {
NOVEL = 0;
PROSE = 1;
PAPER = 2;
POETRY = 3;
}
singular ArticleType article_type = 5 [default = NOVEL];
message Author {
string name = 1;
singular string phone = 2;
}
singular Author author = 6;
repeated int32 article_numberofwords = 7 [packed=true];
reserved 9, 10, 12 to 15;
extensions 100 to 1000;
} extend Article {
singular int32 followers_count = 101;
singular int32 likes_count= 102;
} message Other {
singular string other_info = 1;
oneof test_oneof {
string code1 = 2;
string code2 = 3;
}
}
  • 上面proto文件,我们定义了enum枚举类型,嵌套的消息。甚至对原有的消息进行了扩展,也可以对字段设置默认值。添加注释等,类似C++注释。
  • 此外reserved关键字主要用于保留相关编号标签,主要是防止在更新proto文件删除了某些字段,而未来的使用者定义新的字段时重新使用了该编号标签。这会引起一些问题在获取老版本的消息时,譬如数据冲突,隐藏的一些bug等。所以一定要用reserved标记这些编号标签以保证不会被使用。
  • 当我们需要对消息进行扩展的时候,我们可以用extensions关键字来定义一些编号标签供第三方扩展。这样的好处是不需要修改原来的消息格式。就像上面proto文件,我们用extend关键字来扩展。只要扩展的字段编号标签在extensions定义的范围里。
  • 对于基本数值类型,由于历史原因,不能被protobuf更有效的encode。所以在新的代码中使用packed=true可以更加有效率的encode。注意packed只能用于repeated 数值类型的字段。不能用于string类型的字段。
  • 在消息Other中我们看到定义了一个oneof关键字。这个关键字作用比较有意思。当你设置了oneof里某个成员值时,它会自动清除掉oneof里的其他成员,也就是说同一时刻oneof里只有一个成员有效。这常用于你有许多optional字段时但同一时刻只能使用其中一个,就可以用oneof来加强这种效果。但需要注意的是oneof里的字段不能用singular,repeated关键字。

导入定义

我们总不能都定义在一个文件中。当一个proto文件需要另一个proto文件的时候,我们可以通过import导入。protobuf也提供了包的定义,只要在文件开头定义package关键字即可。

import "test.proto"
package foo.bar;

编译问题

针对不同语言,依据.proto文件编译成我们需要的语言文件。如C++下

protoc -I=SRC_DIR --cpp_out=DST_DIR SRC_DIR/ex.proto

先简单记录这些。

序列化和反序列化及Protobuf 基本使用的更多相关文章

  1. protobuf--数据序列化及反序列化

    ProtoBuf是一种灵活高效的独立于语言平台的结构化数据表示方法,可用于表示通信协议和数据存储等各方面,与XML相比,ProtoBuF更小更快更简单.你可以用定义自己ProtoBuf的数据结构,用P ...

  2. windows环境下protobuf的java操作{编译,序列化,反序列化}

    google protocol buffer的使用和原理 概况: Protocol Buffers(也就是protobuf)是谷歌的语言中立的.平台中立的.可扩展的用于序列化结构化的数据: windo ...

  3. C# 使用 protobuf 进行对象序列化与反序列化

    protobuf 是 google的一个开源项目,可用于以下两种用途: (1)数据的存储(序列化和反序列化),类似于xml.json等: (2)制作网络通信协议. 源代码下载地址:https://gi ...

  4. ProtoBuf序列化和反序列化方法

    最近公司需要将以前的协议全都改成ProtoBuf生成的协议,再将结构体打包和解包过程终于到一些问题 ,无法使用Marshal.SizeOf计算结构体大小,最后找了一下ProtoBuf的文档,可以用它自 ...

  5. Google protobuf序列化以及反序列化

    序列化的目的是将对象持久化到硬盘或者用于网络传输.java也提供了序列化技术,非常简单,只要实现Serializable接口即可.如下: public class commonService impl ...

  6. [Go] 使用protobuf进行序列化和反序列化

    先定义消息类型 orders.proto syntax = "proto2"; package message; message Orders { required int32 o ...

  7. unity探索者之protobuf的序列化和反序列化导致unity崩溃的问题研究

    版权声明:本文为原创文章,转载请声明http://www.cnblogs.com/unityExplorer/p/7574569.html 这两天博主在接微信支付SDK的时候碰到一个非常恶心又诡异的问 ...

  8. 透过byte数组简单分析Java序列化、Kryo、ProtoBuf序列化

    序列化在高性能网络编程.分布式系统开发中是举足轻重的之前有用过Java序列化.ProtocolBuffer等,在这篇文章这里中简单分析序列化后的byte数组观察各种序列化的差异与性能,这里主要分析Ja ...

  9. 大型分布式C++框架《三:序列化与反序列化》

    一.前言  个人感觉序列化简单来说就是按一定规则组包.反序列化就是按组包时的规则来接包.正常来说.序列化不会很难.不会很复杂.因为过于复杂的序列化协议会导致较长的解析时间,这可能会使得序列化和反序列化 ...

随机推荐

  1. 关于解决Git项目本地修改代码之后执行pull操作之后报错的问题

    解决办法: 注意!该方法执行后会导致远程仓库覆盖本地仓库的文件,如果不需要对本地文件进行保存,可以无视,若之后还需要用到,请备份所报错文件! 1.Eclipse中选中项目右键-->Team--& ...

  2. Java集合系列[4]----LinkedHashMap源码分析

    这篇文章我们开始分析LinkedHashMap的源码,LinkedHashMap继承了HashMap,也就是说LinkedHashMap是在HashMap的基础上扩展而来的,因此在看LinkedHas ...

  3. 使用npm install报错-4048 operation not permitted解决

    刚刚使用npm install时一直报错-4048 operation not permitted,也尝试了多种方法,终于使问题得到解决,这里总结几种方法,先贴图: 一:权限问题 首先看到operat ...

  4. 利用object.defineProperty实现数据与视图绑定

    如今比较火的mvvm框架,例如vue就是利用es5的defineProperty来实现数据与视图绑定的,下面我来介绍一下defineProperty的用法. var people= {} Object ...

  5. Shell常用命令整理

    http://blog.csdn.net/junmail/article/details/4602745 1.   ls: 类似于dos下的dir命令 ls最常用的参数有三个: -a -l -F. l ...

  6. 解决导入MySQL数据库提示"Unknown character set: 'utf8mb4'"错误

    今天老左在准备迁移公司一个客户的网站到另外一台服务器中,根据正常的操作备份最新的网页文件和导出数据库,然后在新服务器中创建站点和数据库wget迁移进去解压.因为数据库比较小,所以直接用PHPMyAdm ...

  7. Css雪碧图

    Css雪碧图: CSS雪碧 即CSS Sprite,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法是将小图标和背景图像合并到一张图片上,然后利用css的背景定位来显示需要显示的图片部分. 原理 ...

  8. nodejs+websocket实时聊天系统

    介绍下websocket: webSocket协议本质上是一个基于tcp的协议; 建立一个websocket连接,大体的过程: 1.客户端浏览器首先向服务器发起一个http请求,这个请求和平常的请求有 ...

  9. RGB颜色设置错误

    [UIColor colorWithRed:<#(CGFloat)#> green:<#(CGFloat)#> blue:<#(CGFloat)#> alpha:& ...

  10. Centos7 开放防火墙端口命令

    Centos 7 使用firewalld代替了原来的iptables,使用方法如下: >>>关闭防火墙 systemctl stop firewalld.service       ...