从JSON到Protobuf,深入序列化方案的选型与原理

Java序列化与反序列化全解析:原理、选型、安全与避坑指南 在Java开发中,对象的存储与跨进程传输始终是核心问题。序列化作为将对象状态转换为字节流的机制,是理解缓存、RPC等场景的关键基础。从实现Serializable标记接口到serialVersionUID的版本控制,再到transient字段的排除规则,Java原生序列化提供了完整的对象图处理能力,但同时也存在体积大、跨语言困难与反序列化安全风险等隐患。面对Redis缓存乱码、RPC调用失败等问题,开发者需要根据跨语言需求、性能要求与可读性权衡选择合适的序列化方案,如JSON、Kryo或Protobuf。本 阅读详情

序列化:数据跨越边界的翻译官
序列化(Serialization)用于描述RPC服务接口和数据结构。在RPC通信中,客户端和服务器之间传输的数据通常是结构化的,如调用方法、请求参数、返回值等。这些结构化数据需要通过序列化过程转换为二进制流,以便在网络中进行传输。
目前,常见的跨语言序列化编码方式包括XML、JSON和Protobuf。尽管XML曾经广泛使用,但现在已经逐渐被淘汰。JSON目前正处于其使用高峰,而Protobuf则是一种新兴并且正在快速发展的序列化方式。值得一提的是,gRPC默认选择使用Protobuf作为其序列化方式。

JSON
JSON(JavaScript Object Notation)是一种轻量级的文本数据格式,以其优秀的可读性、灵活性和跨语言兼容性而广受欢迎。由于其结构简单、规范明确,JSON在Web开发、移动应用、API通信等领域得到了广泛应用。同时,JSON还可以与其他技术和工具集成,如RESTful API、NoSQL数据库等,进一步扩展了其应用范围。

// 定义Message 结构体
type Message struct {
	Int  int32  `json:"int"`
	Str  string `json:"str"`
	Bool bool   `json:"bool"`
}

// 将message通过JSON序列化
message := Message{}
message.Int = 12345
message.Str = "hello"
message.Bool = true
marshal, _ := json.Marshal(&message)
fmt.Println(fmt.Sprintf("JSON:%s ", string(marshal)))
fmt.Println(fmt.Sprintf("长度:%d 字节 ", len(marshal)))
fmt.Println(fmt.Sprintf("二进制流:%08b", marshal))

// 打印的二进制流
JSON:{"int":12345,"str":"hello","bool":true} 
长度:39 字节 
二进制流:[01111011 00100010 01001001 01101110 01110100 00100010 00111010 00110001 00110010 00110011 00110100 00110101 00101100 00100010 01010011 01110100 01110010 00100010 00111010 00100010 01101000 011 01101100 01101100 01101111 00100010 00101100 00100010 01000010 01101111 01101111 01101100 00100010 00111010 01110100 01110010 01110101 01100101 01111101]

假设用UTF-8编码,每个字符占用1个字节。估算上面JSON占有的内存数据。
1)字段名占用的内存空间: int (3字节)+ str (3字节)+ str (4字节)= 10字节。
2)字段值占用的内存空间:12345 (5字节)+ hello (5字节)+ true (4字节)= 14字节。需注意JSON中数值和布尔类型会被编码为文本字符串。
3)分隔符和其他符号占用的内存空间::(3字节)+ ,(2字节)+ {}(2字节)+ "(8字节)= 15字节
JSON的内存占用为:10 + 14 + 15 = 39个字节,其中有效的字段值只占14个字节。 可见JSON的内存占有比较大且效率低,这个问题的主要有如下原因。
1)非字符串编码低效:int 字段值,转成 JSON 要五个字节。 bool 字段值占了四个字节。
2)字段名信息冗余:同一个对像,只是字段值不同,每次都要传输相同的字段名。

Protobuf
Protobuf(Protocol Buffers)是由Google开发的一种高效的二进制序列化格式。它设计精巧,旨在提供一种简单、动态、可扩展且性能高效的数据序列化方案。相比于XML和JSON等其他序列化编码方式,Protobuf具有更小的数据体积和更快的数据解析速度,这使得它在处理大量数据和高性能需求的场景中具有显著优势。

// 定义Message .proto文件
message Message {
  int32 int = 1;
  string str = 2;
  bool bool = 3;
}

// 将message通过Protobuf序列化
message := pb.Message{}
message.Int = 12345
message.Str = "hello"
message.Bool = true
marshal, _ := proto.Marshal(&message)
fmt.Println(fmt.Sprintf("长度:%d 字节 ", len(marshal)))
fmt.Println(fmt.Sprintf("二进制流:%08b", marshal))

// 打印的二进制流
长度:12 字节 
二进制流:[00001000 10111001 01100000 00010010 00000101 01101000 01100101 01101100 01101100 01101111 00011000 00000001]

Varint
Varint是一种变长的整数类型,相较于定长的编码方式,更能节省空间。Varint使用每个字节的最高位(Most Significant Bit,MSB),记录字节读取是否结束。 如果MSB 为1 ,表示还有后序字节,一直读到 MSB 为 0 的字节为止。一个int32整型通常占据4个字节也就是32位,但使用Varint编码只需1个字节。

// 常规int32类型值为1二进制表示
0000 0000 | 0000 0000 | 0000 0000 | 0000 0001 

// Varint编码int32类型值为1二进制表示 
0000 0001

wire type
Protobuf将每个字段编码后从逻辑上分为三个部分。

<tag> <type> [<length>] <data>

其中tag 里面会包含两部分信息:字段序号(field number),字段类型(wire type)。tag,type和 length 都用 VarInts 表示。
Protobuf 在 3 版本中定义了 4 种类型 。

0 VarInt 表示int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 64-bit 表示fixed64, sfixed64, double
2 Length-delimited 表示 string, bytes, embedded messages, repeated 字段
5 32-bit 表示fixed32, sfixed32, float

由于3 和 4 表示的类型已经废弃,类型比较少,所以Protobuf 在编码时候只用了 3 bit,实际传输以 (tag<<3)|type 的方式传输。

在这里插入图片描述

使用 tag 的优点是不用重复传输字段名,但也因为没有字段名,所以须维护字段名和 tag 的映射关系。这个映射关系由.proto维护 。
将message通过Protobuf序列化的二进制串,与原始字段名和字段值有如下的对应关系。

在这里插入图片描述

Protobuf在多个方面都展现出与JSON相比的优势。首先,Protobuf的数据更为紧凑,相较于JSON的文本格式,它可以大幅减少数据的存储和传输开销。其次,Protobuf的处理速度更快,由于采用了二进制编码,它能够更快地将二进制数据转换为内存对象。此外,Protobuf还提供了类型安全的保障,通过预先定义消息结构,确保数据的一致性和正确性。
然而,与JSON相比,Protobuf由于采用了二进制编码,Protobuf的数据在可读性方面稍逊一筹。此外,Protobuf需要预先定义消息结构,这增加了一些额外的工作量,并且在消息结构发生变化时,需要同步进行更新。
需要明确的是,序列化并非RPC协议本身,而是将RPC传输的结构化数据(如请求参数、返回值)序列化成二进制流的过程。因此,RPC协议中需要包含序列化标识,以便接收端根据序列化标识将二进制流反序列化成结构化数据。然而,像HTTP/1协议直接将文本数据转换成二进制流,因此不需要额外的序列化标识。
序列化的性能直接影响到RPC协议的性能。一个优秀的序列化编码方式应该在占用更低的内存空间的同时,保持更高的编解码效率。除了JSON和Protobuf之外,还有一些特定语言的序列化编码方式,如Java的Hessian、Kryo等,它们在特定的场景中也可以作为优秀的选择。

总结:没有银弹,只有最合适的选择
构建高效、健壮的服务通信体系,其核心在于制定一套能够有效协调跨服务、跨边界协作的规范与机制。在复杂的异构系统交互中,必须系统性地解决数据格式的统一性、信息传输的高效性以及方法定义的明确性这三大基础问题。
标准化框架(如gRPC): 它们通过整合HTTP/2的流式交互能力和ProtoBuf的统一编解码方案,构建了一个功能完备、开箱即用且具有广泛生态支持的开放RPC体系。这尤其适用于需要跨语言、跨团队协作以及面临复杂多变公网环境的场景。
精简的自研协议: 它们更聚焦于榨取内网环境下的极致性能潜力。通过高度定制、可扩展的报文结构设计和灵活的过程控制,自研协议能够针对特定业务场景和硬件环境进行深度优化,满足对低延迟、高吞吐的严苛要求。
这种“公网标准化”与“内网优化”并存的双轨实践,深刻体现了系统设计中的一个根本逻辑:在标准化带来的互操作性、生态繁荣与特定场景下的极致优化之间,寻求一种动态的、弹性的平衡。 技术决策的目标应是既能有力支撑当前业务的快速发展,又能为未来通信潜能的持续释放奠定坚实基础。

很高兴与你相遇!如果你喜欢本文内容,记得关注哦!

序列化与反序列化实战指南:从原理到安全优化 本文深入探讨Java序列化与反序列化的原理、应用场景及安全优化策略。通过实战案例解析Serializable接口、transient关键字的使用,对比JSON、Protocol Buffers等主流方案,并提供性能调优与安全防护的最佳实践,帮助开发者构建高效安全的序列化体系。 阅读详情

相关推荐

AI 网关一把 Key 接通 Claude Code 与 Codex 实战(附配置)

在研发与 SRE 团队中,通常会通过自建 AI 网关(如 Sub2API 等多上游聚合网关)向工程师发放统一的sk-API Key,背后挂载 OpenAI(GPT 系列)、xAI(Grok 系列)、DeepSeek 等上游账号池。当工程师尝试把同一把sk-密钥同时配置到Codex CLI与Cursor 内置终端协议转发被拒:复合分组(composite)下只有 OpenAI/Grok/DeepSeek 账号,没有原生 Anthropic 账号,Claude Code 调直接返回。/model。

探索云原生与智能化驱动下的安全运维新范式。关注DevSecOps、可观测性、AIOps等前沿领域,与您共赴技术前沿。 139

Go 高性能序列化方案:Protobuf、Msgpack 和 FlatBuffers 性能对比

Protobuf:首选,适合 90% 的 RPC 场景。Schema 是长期资产Msgpack:从 JSON 迁移的平滑方案,适合灵活性和性能的折中:高频只读场景的利器,但写入复杂,不通用迁移建议:先对性能最敏感的热路径做序列化切换,不要一次性全量迁移。用 benchmark 数据指导选型,而不是凭经验猜测。

好代码自己会说话,烂代码才需要注释来圆谎 4757

FPGA:UART串口接收(高干扰情况)

在上一篇文章中介绍过UART串口接收模块,其中一个需要优化的方向就是在高干扰情况下,如何实现可靠的UART串口接收任务。

weixin_50164178的博客 1672

序列化原理:数据翻译——Easy-Vibe 后端核心指南

> 本篇技术指南源自 Easy-Vibe(Datawhale 开源项目制学习仓库)后端附录《序列化原理:数据的翻译》,围绕"数据如何在网络上传输"这一核心问题,系统讲解序列化(Serialization)与反序列化(Deserialization)的定义、四大常见格式(JSON / XML / Protobuf / MessagePack)的优劣对比、跨语言序列化方案选型、性能数据以及日期丢失、循

gitblog_01121的博客 238

MaxEnt物种分布预测中的常见误区与优化技巧:如何提高模型准确率

本文深入探讨了MaxEnt物种分布预测模型从基础应用到精准预测的进阶实践。针对模型准确率提升,文章系统分析了环境变量筛选、模型参数调优、结果批判性解读等核心环节的常见误区,并提供了基于生态位模型原理的深度优化技巧,帮助研究者产出更可靠、可解释的预测结果。

weixin_29219539的博客 594

【编号326】全国地灾数据全国25万多个地质灾害点空间分布数据

全国地质灾害点分布数据涵盖25万多个各类灾害点信息,为灾害防治提供重要依据。通过分析灾害分布规律,可识别高风险区,指导监测预警、应急避险和基础设施建设。多地成功案例(如湖北兴山崩塌避险、重庆长寿滑坡预警、湖南"挪床行动")证明,提前预警和科学防治能有效避免人员伤亡。云南省2024年通过预警体系成功避让31起灾害,保护1342人生命安全。这些实践表明,地质灾害防治需结合科技手段与群防体系,实现早预警、早处置。

千奇百怪无奇不有 1472

从内存到网络:深入理解对象序列化

首先我们的编写的代码最终都会变成计算机能够执行的机器码指令,编译型的语言一步到位生成机器码,解释型的语言通过解释器或者虚拟机来翻译成机器码。那么我们的程序处理的数据是怎么从内存里进入到网络呢毫无疑问,数据进入网络或者磁盘肯定是通过IO操作实现的,比如Java中的InputStream和 OutputStream以及C++中的ifstream和ofstream函数 等等。但是数据在内存中的组织结构千奇百怪,有各种简单类型的数据,也有复杂类型的对象以及各种奇奇怪怪的数据结构。

代码洁癖症患者 2万+

Lumerical INTERCONNECT 中的自相位调制 (SPM) 仿真实践指南

本文详细介绍了在Lumerical INTERCONNECT中进行自相位调制(SPM)仿真的实践指南。从SPM的基础物理原理出发,深入解析非线性薛定谔方程和克尔效应,到INTERCONNECT中NLSE波导元件的配置技巧,以及时域与频域中SPM效应的观测方法。文章还提供了常见问题排查和进阶联合仿真技巧,帮助用户高效完成从仿真到实测的校准过程。

weixin_42565652的博客 187

一文吃透Java序列化:常用方式、工具及场景选型指南

本文系统梳理了Java生态中常用的序列化方式与工具。首先分析了序列化的核心需求与评价维度,包括兼容性、性能、易用性等功能特性。然后详细介绍了8种主流序列化方案:原生JDK序列化、JSON系列(Jackson/Gson/Fastjson)、Protobuf、Hessian、Kryo等,从核心原理、基础用法到优缺点进行全面对比。

m0_58782205的博客 1643

低照度与极端天气环境中的YOLOv8优化:CPA-Enhancer网络的应用与分析

为了克服上述问题,本文提出了一种名为的网络改进方案。CPA-Enhancer通过引入链式思考机制和改进的注意力机制,有效地提升了YOLOv8在低照度和复杂天气下的表现。本文提出了针对低照度和恶劣天气条件下目标检测的YOLOv8改进方案——CPA-Enhancer链式思考网络。通过引入低照度图像增强和多尺度特征融合技术,CPA-Enhancer显著提高了YOLOv8在低光照、雾霾、雨雪等环境下的检测性能。实验结果表明,CPA-Enhancer相较于原始YOLOv8,在多个指标上都有显著的提升,尤其是在mAP。

博客 1565

OpenClaw实战五|企业文档AI助理:对接内部知识库+自动答疑+文档生成,员工自助查资料零等待

企业最大的隐性成本,不是设备、不是房租,而是内部知识的混乱与流失。OpenClaw企业文档AI助理,本质是给企业做了一个7×24小时在线、永不疲倦、精准无误、自动更新的内部知识管家。它不替代HR、行政、IT,而是把他们从无穷无尽的重复问答、机械文档编写里解放出来,去做更有价值的管理、服务、优化工作。对中小企业来说,不用买昂贵的知识库系统、不用招开发、不用做复杂集成,一台私有化服务器,两天就能落地,性价比拉满。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 144

序列化与反序列化核心原理、实战避坑及安全防护指南

序列化是将内存对象转换为可存储或传输格式的过程,反序列化则相反,二者是跨进程通信、数据持久化和跨语言交互的基础。其核心原理涉及数据表示、编码与传输三层结构,主流方案包括JSON、Protobuf和Java原生序列化。合理选择序列化协议能显著提升系统性能与可维护性,广泛应用于微服务、缓存和消息队列等场景。然而,反序列化漏洞可能引发远程代码执行,需通过白名单校验、避免原生反序列化等措施防护。本文深入剖析序列化机制,结合Jackson与Redis实战,并给出安全防护与性能优化建议。

weixin_30613727的博客 279

从 Open SQL JOIN 走向 ABAP CDS Association:把查询写成可复用的数据模型

摘要: 本文通过飞行模型示例,对比了ABAP中三种表关联实现方式:Open SQL JOIN、CDS显式JOIN和CDS Association。重点解析了Association的本质是将表关系声明为数据模型语言,使用时通过路径表达式按需展开为JOIN。文章指出路径表达式在不同位置会默认展开为不同JOIN类型(如SELECT列表默认为LEFT OUTER),并演示了如何用[inner]强制指定INNER JOIN。最后结合S/4HANA实际案例,说明Association通过中心化关系定义和路径复用,能有效

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 384

Dubbo序列化优化:Hessian2、JSON、Protobuf选型与实践

序列化是RPC通信的核心环节,直接决定接口性能、带宽占用与系统稳定性。不同序列化方案在数据体积、编解码速度、跨语言能力和开发成本上差异显著:Hessian2作为Dubbo默认协议,兼容性好且改动成本低;JSON可读性高但解析开销大;Protobuf凭借紧凑的二进制格式和极快解析速度,成为高并发、海量数据场景的首选。实际选型需综合调用链路的性能敏感度、团队技术栈及维护成本,并通过压测验证效果。本文围绕Dubbo框架,结合线上故障案例,系统对比三种主流序列化方案的原理与适用场景,并给出配置方法、踩坑记录和迁移建

weixin_29722783的博客 200

《QGIS快速入门与应用基础》010:下载过程中常见问题(如网速慢、文件损坏)

针对QGIS下载过程中的常见问题提供了系统解决方案。主要解决下载速度慢(≤100KB/s)和文件损坏两大核心问题:通过切换国内镜像源(如清华大学、阿里云)、使用专业下载工具提升速度;采用MD5/SHA256校验确保文件完整性,并排查存储介质和杀毒软件干扰。文章还包含macOS权限问题、Linux依赖缺失等高频问题的速解方案,并附详细的排查流程图和预防技巧,帮助用户顺利完成QGIS下载。后续将详细介绍安装流程,适合零基础用户参考。

LuckyHanMo的博客 482

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Java序列化与反序列化原理、坑位与选型实战

序列化是将内存中的Java对象转换为字节数组的过程,反序列化则是逆向还原。作为跨进程、跨存储的基础能力,它支撑着Redis缓存、RPC通信、消息队列及深拷贝等常见场景。Java原生通过Serializable标记接口与ObjectInputStream/ObjectOutputStream实现,底层需处理对象图、循环引用与serialVersionUID版本兼容。实际工程中,字段增删、transient关键字、反序列化安全漏洞及框架选型(JSON、Kryo、Protobuf)都是高频关注点。掌握其原理与避坑

weixin_30843121的博客 196

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

序列化原理精讲:从数据翻译到前后端通信的完整实战指南

本文是 Datawhale easy-vibe 项目「后端与服务器」系列教程中的核心章节,围绕"数据如何在网络上传输"这一根本问题,系统讲解序列化(Serialization)与反序列化(Deserialization)的原理、常见格式选型、性能对比与实战排错方法。读完本文,你将掌握 JSON / XML / Protobuf / MessagePack 四种主流格式的优劣与适用场景,能够独立完成

gitblog_00026的博客 418

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Java序列化与反序列化全解析:原理、实战与面试考点

在Java开发中,对象无法直接写入文件或通过网络传输,序列化与反序列化正是解决这一问题的核心技术。通过将对象转化为字节序列,Java程序能够实现数据持久化、缓存存储、远程过程调用(RPC)以及深拷贝等能力。理解序列化原理,掌握Serializable接口、serialVersionUID、transient关键字及自定义读写方法,是每个后端工程师的必备技能。同时,反序列化安全漏洞历来是系统攻防的高频风险点,如何防范恶意字节流攻击、选择合适序列化方案(如JSON、Kryo、Protobuf)直接关系到系统性能

weixin_33552698的博客 180

Java序列化从入门到精通:核心原理、实战应用与进阶优化

本文深入浅出地讲解了Java序列化的核心概念与实践应用。通过乐高模型的生动类比,阐明了序列化将对象转换为字节序列的本质。文章重点分析了序列化在对象持久化、跨进程通信和框架支持中的关键作用,并提供了三步实现方案:定义Serializable接口类、使用ObjectOutputStream序列化、通过ObjectInputStream反序列化。文中还包含完整的代码示例,展示了如何正确处理transient字段和serialVersionUID,帮助开发者规避常见问题。作为Java开发的基础技能,掌握序列化技术对

从零开始,掌握网络安全。提供全面的网络安全教程、攻防演练技巧和行业动态。 656

应用层协议实战指南:从HTTP、HTTPS到序列化与反序列化

在计算机网络中,应用层协议是网络通信的基石,它定义了数据交换的语法、语义与时序。理解HTTP、HTTPS以及序列化与反序列化机制,是后端开发、接口联调和网络排障的核心能力。HTTP作为最广泛的应用层协议,其报文结构、状态码、连接管理直接影响系统性能与稳定性;HTTPS通过TLS混合加密、证书链验证保障数据传输的机密性与完整性。而序列化技术则在跨语言、跨平台的数据交换中扮演关键角色,JSON、Protobuf等格式各有适用场景与坑点。掌握协议原理与实际排查技巧,能帮助开发者快速定位接口超时、报文乱码、证书错误

WGH100817的博客 347

Java序列化技术解析与性能优化实践

序列化是将内存对象转换为可传输或存储格式的核心技术,在分布式系统和微服务架构中尤为重要。其原理是通过特定算法实现对象状态的持久化,涉及反射、字节码生成等底层机制。高效的序列化方案能显著提升系统吞吐量,不同技术方案在性能上可能相差数十倍。主流实现包括JDK原生序列化、JSON方案(如Jackson/Gson)和二进制协议(如Protobuf/Kryo),适用于RPC通信、缓存存储等场景。特别是Kryo和Protobuf等高性能方案,通过预编译和二进制编码大幅优化了处理速度,在电商秒杀、游戏实时交互等对延迟敏感

weixin_34199764的博客 216

Java序列化从入门到实战:serialVersionUID、反序列化安全与选型指南

在分布式系统与缓存应用中,对象持久化与跨进程传递离不开序列化技术。序列化将内存对象转换为字节流,反序列化则恢复对象状态,支撑网络通信、消息队列、Redis缓存等核心场景。Java通过Serializable接口与ObjectOutputStream/InputStream实现默认机制,但serialVersionUID的显式声明、transient字段的排除、继承链的兼容性等细节直接影响稳定性。同时,反序列化不可信数据可能触发恶意代码执行,防御需结合白名单过滤与字节流签名。生产选型还需要权衡Java原生序列

weixin_33416697的博客 251
上一篇: gRPC不是银弹:为内网极致性能,如何设计自己的RPC协议?
下一篇: “卧槽,系统又崩了!”——别慌,这也许是你看过最通俗易懂的分布式入门
milanyangbo
博客等级 码龄11年 199粉丝 67原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

milanyangbo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值