移动开发中的数据序列化:本质、格式与工作方式

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

序列化和反序列化是将对象转换为可传输或存储格式的基本过程。在移动开发中,这些机制在每个网络请求、状态保存和进程间通信中都有使用。根据MDN Web Docs,2024JSON仍然是最流行的序列化格式,在Web和移动应用中都超过了XML和Protocol Buffers。

要点

  • 序列化 — 将对象转换为字节序列以进行传输或存储
  • 反序列化 — 从字节表示中恢复对象的反向过程
  • JSON — 人类可读且所有平台都支持的文本格式
  • Protocol Buffers — 谷歌的二进制格式,速度快、体积紧凑
  • XML — 可扩展标记语言,支持验证模式(XSD)和命名空间

序列化与反序列化的本质

序列化是将应用程序对象转换为适合通过网络发送或存储在磁盘上的格式的过程。反序列化执行反向转换,从接收到的数据中恢复对象。在移动开发中,序列化应用于API请求、屏幕状态保存、缓存以及通过Intent或Bundle进行数据传输。

何时需要

应用组件之间或应用与服务器之间的每次交互都需要序列化。REST API以JSON或XML格式传输数据,gRPC使用Protocol Buffers,Android上的进程内通信使用Parcelable。没有序列化,就不可能将复杂对象传递到进程边界之外或将其保存到数据库中。

kotlin
// 序列化的一般原则
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// 序列化:对象 -> JSON
fun serializeUser(user: User): String {
    return """{"id":${user.id},"name":"${user.name}","email":"${user.email}"}"""
}

// 反序列化:JSON -> 对象
fun deserializeUser(json: String): User? {
    // 将JSON解析为对象
    return Gson().fromJson(json, User::class.java)
}
格式大小速度可读性类型化
JSON中等动态
XML中等XSD模式
Protocol Buffers非常高严格.proto
FlatBuffers最高严格.fbs

JSON — 移动开发的主要格式

JSON(JavaScript Object Notation)是一种基于JavaScript对象语法的轻量级文本格式。JSON支持字符串、数字、布尔值、数组和嵌套对象,覆盖了移动应用中大多数数据传输场景。该格式独立于平台:每个生态系统都提供内置的解析工具。

JSON相比其他格式的优势

JSON因其简单性和通用性而胜出。开发者不需要模式即可进行基本使用 — 结构在解析过程中动态确定。格式的可读性简化了调试和测试:服务器的响应可以在任何开发者工具中查看。在两个移动平台上,JSON都可以原生处理,无需连接第三方库。

swift
// Codable — Swift中的原生JSON序列化
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

let jsonString = """{"id":1,"name":"John","email":"john@test.com"}"""
let jsonData = Data(jsonString.utf8)
let decoder = JSONDecoder()
let user = try! decoder.decode(User.self, from: jsonData)

谷歌的Protocol Buffers

Protocol Buffers(protobuf)是谷歌为高性能系统开发的二进制序列化格式。与JSON不同,protobuf需要在.proto文件中预先定义模式,但提供显著更小的数据量和更高的处理速度。该格式用于gRPC、Firebase Firestore和谷歌的内部服务。

.proto文件的结构

protobuf模式描述带有类型化字段的消息,每个字段都有一个唯一的编号。protoc编译器在目标语言中生成类,这些类自动执行序列化和反序列化。Protobuf通过添加和删除字段的规则支持模式的演进,而不会失去向后兼容性。

cpp
// 在user.proto中定义模式
syntax = "proto3";

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
  repeated string roles = 4;
}

// 在Kotlin中生成的代码
val user = UserProto.User.newBuilder()
    .setId(1)
    .setName("John")
    .setEmail("john@test.com")
    .build()

val bytes: ByteArray = user.toByteArray()

XML及其应用

XML(可扩展标记语言)是一种具有严格结构、支持命名空间和通过XSD模式进行验证的格式。XML在紧凑性和解析速度方面不如JSON,但在Android开发中仍然很受欢迎,用于布局文件、AndroidManifest、资源和Gradle配置。在iOS上,XML用于plist文件和某些旧版服务。

在Android上解析XML

Android提供了三种解析XML的方式:DOM(将整个文档加载到内存中)、SAX(事件驱动的流式解析)和XmlPullParser(混合方法)。XmlPullParser是移动设备的推荐选择,因为它可以有效利用有限的内存,并允许在读取时处理文档。

kotlin
// Android上的XmlPullParser
fun parseUserXml(inputStream: InputStream): User? {
    val parser = Xml.newPullParser()
    parser.setInput(inputStream, Xml.Encoding.UTF_8.name)

    var id: Int? = null
    var name: String? = null
    var email: String? = null

    while (parser.next() != XmlPullParser.END_DOCUMENT) {
        if (parser.eventType == XmlPullParser.START_TAG
            && parser.name == "email") {
            email = parser.nextText()
        }
    }
    return User(id!!, name!!, email!!)
}

iOS和Android上的序列化

每个平台都提供自己的序列化工具。在iOS上,主要机制是Codable协议以及JSONEncoder和JSONDecoder,对于Objective-C则是NSJSONSerialization。Android使用Gson、Moshi和kotlinx.serialization库。对于进程间的数据传输,Android使用Parcelable,iOS使用NSKeyedArchiver。Kotlin项目越来越常选择kotlinx.serialization — JetBrains的解决方案,它支持多平台且不依赖于反射,通过Kotlin编译器插件在编译阶段生成序列化器。

Android上的Parcelable与Serializable

Android支持两种用于Intent和Bundle的序列化机制。Serializable是使用反射的标准Java机制,导致性能低下。Parcelable是Android特有的协议,需要手动实现writeToParcel和createFromParcel方法,但由于直接操作字节,速度快了数十倍。

kotlin
// Android上的Parcelable
@Parcelize
data class UserParcel(
    val id: Int,
    val name: String,
    val email: String
) : Parcelable

// 通过Intent传输
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", userParcel)
startActivity(intent)

在iOS上,控制器之间的数据传输使用Codable预先序列化为Data,而进程间通信则使用NSKeyedArchiver将对象转换为二进制Property List格式。SwiftUI中的现代项目更倾向于通过JSONEncoder对数据进行编码,以便在应用程序模块之间传输。

序列化中的安全性

不可信数据的错误反序列化可能导致漏洞。通过序列化的攻击利用了Java中被覆盖的readObject方法或第三方库的不安全反序列化器。在Android上,应避免对来自不可信来源的数据使用Serializable,而应使用Parcelable或在反序列化后手动验证所有字段。在iOS上,JSONDecoder默认对类型严格要求,但在使用JSONSerialization时,开发者必须通过条件转换检查类型。

为项目选择格式

选择序列化格式时,需要考虑性能要求、数据大小和兼容性。对于REST API和微服务架构,最佳选择仍然是JSON — 它被所有平台和语言支持。对于高负载系统和流量受限的移动应用,更推荐Protocol Buffers,它提供更小的体积和更快的反序列化。XML仅适用于配置场景和与旧版系统的集成。在现代项目中,FlatBuffers也越来越受欢迎 — 这是一种无需反序列化阶段的二进制格式,用于游戏引擎和延迟极低的应用。每种格式都有自己的定位,正确的选择直接影响应用程序的运行速度和消耗的流量。

常见问题

用简单的话说什么是序列化?

序列化是将应用对象打包成可以通过网络发送或保存到文件的格式。想象你给一个物品拍照 — 照片就是序列化,而从照片中恢复物品就是反序列化。

JSON和Protocol Buffers有什么区别?

JSON是一种人类可读的文本格式,不需要模式。Protocol Buffers是一种带有必需模式(.proto)的二进制格式,体积更小、速度更快。Protobuf用于高负载系统,JSON用于通用兼容性。

什么时候使用XML代替JSON?

XML仍然是配置文件(AndroidManifest、布局资源)、复杂嵌套文档和通过XSD进行严格验证的系统的标准。XML也应用于需要命名空间支持的SOAP协议和旧版系统。

Swift中的Codable是什么?

Codable是一个Swift协议,结合了Encodable和Decodable,用于自动序列化和反序列化。编译器为结构或类的所有属性生成encode(to:)和init(from:)方法的实现。

哪一个更快:Parcelable还是Serializable?

Parcelable比Serializable快得多,因为它不使用反射并直接将字段写入字节流。在现代设备上,差异可以达到Parcelable快10倍的水平。

总结

  • 序列化 — 将对象转换为传输格式,反序列化 — 反向恢复
  • JSON — 在REST API和移动应用中使用的通用文本格式
  • Protocol Buffers — 谷歌的二进制格式,用于具有固定模式的高性能场景
  • XML — 通过XSD进行验证的格式,应用于配置和旧版系统
  • Parcelable(Android)Codable(iOS) — 用于组件间数据传输的平台级序列化机制
  • 序列化的安全性至关重要:不可信数据在反序列化时可能导致漏洞

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

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

讨论项目

另请阅读