在本文中,我们探讨 JSON 和 Protocol Buffers 数据格式之间的主要区别,以便在为我们的应用程序制定数据编码策略时做出明智的决策。
协议缓冲区(Protobuf) 和JSON是流行的数据序列化格式,但在可读性、性能、效率和大小方面存在显著差异。
在本教程中,我们将比较这些格式并探讨它们的利弊。当我们需要选择其中一种格式时,这将帮助我们根据用例做出明智的决定。
可读性和架构要求
Protobuf 需要预定义模式来定义数据的结构。这是一项严格要求,否则我们的应用程序无法解释二进制数据。
为了更好地理解,让我们看一个示例schema.proto文件:
syntax = "proto3";
message User {
string name = 1;
int32 age = 2;
string email = 3;
}
message UserList {
repeated User users = 1;
}
此外,如果我们看到base64 编码的 Protobuf 示例消息,它会缺乏人类可读性:
ChwKBUFsaWNlEB4aEWFsaWNlQGV4YW1wbGUuY29tChgKA0JvYhAZGg9ib2JAZXhhbXBsZS5jb20=
我们的应用程序只能结合模式文件来解释这些数据。
另一方面,如果我们要以 JSON 格式表示相同的数据,则无需依赖任何严格的模式:
{
"users": [
{ "name": "Alice", "age": 30, "email": "alice@example.com" },
{ "name": "Bob", "age": 25, "email": "bob@example.com" }
]
}
此外,编码后的数据完全可以被人类阅读。
但是,如果我们的项目需要对 JSON 数据进行严格验证,我们可以使用JSON Schema,这是一个用于定义和验证 JSON 数据结构的强大工具。虽然它提供了显着的好处,但它的使用是可选的。
模式schema结构演化
Protobuf 强制执行严格的架构,确保强大的数据完整性,而 JSON 可以促进读取时架构的数据处理。让我们了解这两种数据格式如何以不同的方式支持底层数据架构的演变。
消费者解析的向后兼容性
向后兼容性意味着新代码仍然可以读取旧代码编写的数据。因此,它要求新版本能够正确地反序列化使用旧架构版本序列化的数据。
向后兼容性
为了确保与 JSON 的向后兼容性,应用程序应设计为在反序列化过程中忽略无法识别的字段。此外,消费者应为任何未设置的字段提供默认值。使用协议缓冲区,我们可以直接在架构本身中添加默认值,从而增强兼容性并简化数据处理。
此外,Protobuf 的任何架构更改都必须遵循最佳实践以保持向后兼容性。如果我们要添加新字段,则必须使用以前未使用过的唯一字段编号。同样,我们需要弃用未使用的字段并保留它们,以防止重复使用可能破坏向后兼容性的字段编号。
虽然我们可以在使用两种格式的同时保持向后兼容性,但是协议缓冲区的机制更加正式和严格。
消费者解析的前向兼容性
向前兼容性意味着旧代码可以读取新代码编写的数据。它要求旧版本能够正确地反序列化新架构版本序列化的数据。
前向兼容性
由于旧代码无法预测可能发生的所有数据语义变化,因此保持向前兼容性更加困难。为了实现向前兼容性,旧代码必须忽略未知属性并依赖新模式来保留原始数据语义。
对于 JSON,应用程序应设计为明确忽略未知字段,这可以通过大多数 JSON 解析器轻松实现。相反,Protocol Buffers 具有忽略未知字段的内置功能。因此,protobufs 可以放心地忽略未知字段。
最后,需要注意的是,删除必填字段会破坏两种情况下的前向兼容性。因此,建议的做法是弃用这些字段并逐步删除它们。对于 JSON,一种常见的做法是在文档中弃用这些字段并告知消费者。另一方面,协议缓冲区允许使用更正式的机制来弃用架构定义中的字段。
序列化、反序列化和性能
JSON 序列化涉及将对象转换为基于文本的格式。另一方面,Protobuf 序列化将对象转换为紧凑的二进制格式,同时遵守.proto架构文件中的定义。
由于 Protobuf 可以引用架构来识别字段名称,因此在序列化时无需将它们与数据一起保留。因此,Protobuf 格式比保留字段名称的 JSON 更节省空间。
从设计上来说,Protobuf 在效率和性能方面通常优于 JSON。它通常占用更少的存储空间,并且通常比 JSON 数据格式更快地完成序列化和反序列化过程。
何时使用 JSON
JSON 是 Web API(尤其是RESTful服务)的事实标准。这主要归功于其丰富的工具和库生态系统以及与 JavaScript 的固有兼容性。
此外,基于文本的特性使其易于调试和编辑。因此,使用 JSON 作为配置数据是一种自然的选择,因为配置应该易于人类理解和编辑。
另一个使用 JSON 格式的有趣用例是日志记录。由于其无模式特性,它提供了极大的灵活性,可以将来自不同应用程序的日志收集到一个集中位置,而无需维护严格的模式。
最后,需要注意的是,使用 Protobuf 时,需要特殊的架构感知客户端和其他工具,而对于 JSON,则不需要特殊的客户端,因为 JSON 是纯文本格式。因此,在开发原型或 MVP 解决方案时,我们可能会从 JSON 格式中受益,因为它允许我们以更少的努力引入更改。
何时使用协议缓冲区
协议缓冲区在网络上的存储和传输方面非常高效。此外,它们通过模式定义强制执行严格的数据完整性规则。因此,我们很可能会在此类用例中受益于它们。
处理实时分析、游戏和金融系统的应用程序需要超高性能。因此,我们必须评估在这些场景中使用 Protobuf 的可能性,尤其是对于内部通信。
此外,分布式数据库系统可以从 Protobuf 的小内存占用中受益。因此,协议缓冲区是编码数据和元数据以实现高效数据存储和高性能数据访问的绝佳选择。