移动开发中的数据序列化 — 什么是、格式及工作原理

作者: IT Sectr 发布日期: 2026-03-08 阅读时间: 8 分钟

序列化是将对象或数据结构转换为适合通过网络传输或保存到文件的序列格式的过程。相反的过程,反序列化,将数据恢复到原始状态。根据MDN Web Docs,序列化对任何进程间通信都是必不可少的。序列化是REST API、缓存和应用程序组件之间数据交换的基础。

要点

  • 序列化 — 将对象转换为数据流以便传输或存储
  • JSON — REST API和网络通信的主要文本格式
  • Protobuf — 具有最佳性能和紧凑性的二进制格式
  • XML — 适合企业级和Android开发的严格验证格式
  • 选择格式 取决于性能和兼容性要求

什么是序列化?

序列化是将内存中的对象转换为线性字节或字符序列的过程,可以通过网络传输、保存到文件或传递给另一个进程。没有序列化,网络通信、状态存储和进程间通信是不可能的。

序列化包括两个相反的过程。直接过程(序列化)将数据打包成传输格式。相反过程(反序列化)将数据恢复为对象。反序列化对安全性至关重要:不正确的输入数据可能导致应用程序中的漏洞。

在移动应用开发中,序列化无处不在:向服务器发送请求和处理响应、屏幕旋转时保存应用状态、在磁盘上缓存数据以及通过Intent(Android)或Segue(iOS)在屏幕间传输数据。

序列化的主要任务

  • 网络通信 — 客户端和服务器之间的数据传输
  • 状态存储 — 应用程序数据的保存和恢复
  • 缓存 — 为离线访问保存请求结果
  • 跨平台 — 不同语言系统间的数据交换
  • 日志记录 — 将对象序列化以写入日志

主要序列化格式

序列化格式分为文本和二进制。文本格式(JSON、XML)可以被人类阅读,不需要工具来查看。二进制格式(Protobuf、FlatBuffers、MessagePack)更紧凑、更快,但不经过反序列化无法阅读。选择格式是性能和调试便利性之间的折衷。

除了JSON、XML和Protobuf外,还有专门的格式:Google的FlatBuffers适合游戏和AR、MessagePack——JSON的紧凑二进制替代品、Apache的Avro适合Kafka中的大数据、YAML——支持注释的配置格式。

格式 类型 模式 大小 速度
JSON 文本 可选 中等 中等
XML 文本 XSD
Protobuf 二进制 必须
FlatBuffers 二进制 必须 最高
MessagePack 二进制
Avro 二进制 JSON Schema

移动开发中的序列化

序列化在移动平台上有其特定:流量有限、处理器较弱以及屏幕旋转时保存状态的必要性。在Android上使用Gson、Moshi、Kotlinx Serialization。在iOS上使用Codable、JSONSerialization、PropertyListEncoder。正确选择库会对应用程序的性能产生关键影响。

Kotlinx Serialization——JetBrains为Kotlin Multiplatform Mobile打造的现代库。它支持JSON、Protobuf、CBOR和自定义格式。代码生成通过Kotlin Serialization插件在编译阶段完成,无需反射即可确保高性能。

Kotlinx Serialization(Kotlin Multiplatform)

Kotlinx Serialization库使用@Serializable注解用于类,并使用编译器插件生成序列化器。这确保了高性能和类型安全。默认格式是JSON,但其他格式也可通过额外模块支持。

kotlin
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import kotlinx.serialization.decodeFromString

@Serializable
data class Project(
    val id: Int,
    val name: String,
    val platforms: List<String>,
    val active: Boolean
)

val json = Json {
    prettyPrint = true
    ignoreUnknownKeys = true
    encodeDefaults = true
}

fun main() {
    val project = Project(1, "MobileApp",
        listOf("Android", "iOS"), true)

    // 序列化
    val jsonString = json.encodeToString(project)

    // 反序列化
    val restored = json.decodeFromString<Project>(jsonString)
}

iOS上的Codable(Swift)

Codable协议——Swift中内置的序列化机制。它结合了Encodable(序列化)和Decodable(反序列化)协议。JSONEncoder和JSONDecoder自动处理嵌套结构、数组、可选值和通过CodingKeys的自定义键。

swift
import Foundation

struct AppConfig: Codable {
    let appName: String
    let version: String
    let features: [String]
    let isProduction: Bool
}

let config = AppConfig(
    appName: "MyApp",
    version: "2.1.0",
    features: ["push", "analytics", "offline"],
    isProduction: true
)

let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]

guard let data = try? encoder.encode(config) else { return }
let jsonString = String(data: data, encoding: .utf8)

性能和格式比较

性能序列化格式根据三个指标评估:消息大小、序列化速度和反序列化速度。对于移动应用,这三者都很重要:大小影响流量和加载时间,速度影响界面响应性和应用启动时间。

Protobuf和FlatBuffers凭借二进制表示展示了最佳结果。FlatBuffers的不同之处在于它不需要单独的反序列化步骤——数据直接从二进制缓冲区读取,这对于要求最低延迟的游戏和AR应用非常理想。尽管性能较低,JSON凭借其简单性和普遍性仍然是REST API最流行的格式。

场景 推荐格式 原因
REST API JSON 普遍性、可读性、支持
微服务 Protobuf 紧凑性、速度、gRPC
游戏 / AR FlatBuffers Zero-copy、最低延迟
大数据 Avro 与Kafka和Hadoop兼容
配置 YAML 注释、可读性
Android布局 XML 平台标准

对比测试

在1000个用户对象集上的实践测试显示:Protobuf创建12KB的消息(JSON——85KB,XML——120KB)。序列化时间:Protobuf——2毫秒,JSON——8毫秒,XML——25毫秒。这些数据使得二进制格式成为高负载系统和流量有限的移动应用的首选。

数据序列化示例

示例展示了同一对象在不同格式中的序列化。这有助于直观地比较大小和可读性。同一个User对象将在JSON、XML和Protobuf中序列化——可以清楚地看到JSON比XML更紧凑,而Protobuf是最紧凑的,同时不可读。

三种格式中的同一对象

JSON——最简主义语法,键在引号中,值为不同类型。占用80个字符。可读性高,视觉结构清晰。适合开发和调试速度重要的API。

XML——每个元素裹在开始和结束标签中。占用150个字符。可读性中等,结构严格。适合文档流程和需要通过XSD验证的系统。

Protobuf——二进制,这些数据占用32字节。不可读——需要反序列化才能查看。最小大小使其成为高负载系统和移动应用的理想选择。

json
{
  "id": 42,
  "name": "IT Sectr",
  "email": "team@itsectr.com",
  "role": "admin",
  "active": true
}
xml
<user>
    <id>42</id>
    <name>IT Sectr</name>
    <email>team@itsectr.com</email>
    <role>admin</role>
    <active>true</active>
</user>

序列化最佳实践

最佳实践帮助避免典型错误并为项目选择正确的序列化策略。遵循这些建议可以提高性能、安全性和代码可维护性。

移动开发建议

  1. 根据场景选择格式 — REST API用JSON,gRPC和微服务用Protobuf
  2. 避免Java Serializable — 缓慢且不安全的机制,使用Kotlinx Serialization或Moshi
  3. 忽略未知键 — 配置解析器跳过模型中不存在的字段
  4. 缓存反序列化的数据 — 避免重复解析相同数据
  5. 验证输入数据 — 在反序列化时检查边界和类型

安全性和序列化

序列化安全——至关重要的方面,尤其是从不可信来源反序列化数据时。反序列化攻击可能导致远程代码执行(RCE),这是网络和移动应用中最危险的漏洞之一。最著名的案例与Java Serializable和Python pickle有关。

Protobuf和JSON具有内置的防护机制,因为它们只处理数据,而不是任意对象。相反,Java Serializable可以恢复classpath中可用的任何类,这使得它在接受来自外部来源的数据时具有危险性。在Android上,建议使用Kotlinx Serialization或Moshi代替标准的Java Serialization。

额外的安全措施:为输入数据大小设置限制,在反序列化前验证模式,不要相信HTTP头中的Content-Type,为允许的类使用白名单。定期更新序列化库,因为其中的漏洞会定期被发现和修复。

常见问题

序列化和编组有什么区别?

序列化将对象转换为字节序列,编组(marshalling)在保持类型和结构的同时在不同地址空间之间传输数据。编组包括序列化作为过程的一部分,但也可能包括引用编码和内存管理。

哪种序列化格式最快?

Google的FlatBuffers凭借零拷贝反序列化提供了最高速度——数据直接从二进制缓冲区读取,无需转换。Protobuf位居第二,JSON第三。XML是常见格式中最慢的。

Android该选择什么:Gson、Moshi还是Kotlinx Serialization?

Kotlinx Serialization是Kotlin新项目的最佳选择:编译器生成、支持Kotlin Multiplatform、空安全。Moshi适合Java项目,性能优于Gson。Gson是最简单的入门库,但较慢且使用反射。

如何序列化含有循环引用的对象?

循环引用会导致序列化时无限递归。解决方案:使用ID引用代替对对象的直接引用,应用特殊的序列化适配器(例如Jackson中的@JsonIgnore),或重新设计数据模型以消除循环。

序列化会影响应用安全性吗?

,尤其是从不可信来源反序列化数据。反序列化漏洞可能导致远程代码执行。建议:不要从不可信来源反序列化数据,在反序列化时使用类白名单,并在处理前验证数据模式。

总结

  • 序列化将对象转换为数据流以便传输和存储,反序列化恢复它们
  • JSON — REST API标准,XML — 文档流程,Protobuf — 微服务和高负载
  • 二进制格式(Protobuf、FlatBuffers)比文本格式紧凑3-10倍且快3-10倍
  • 在Android上建议Kotlinx Serialization,在iOS上建议内置的Codable
  • 缓存反序列化的数据减少了处理器负荷并加快了应用
  • 安全性反序列化至关重要 — 检查输入数据并使用白名单
  • 选择格式 — 在可读性、性能和兼容性之间折衷

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读