JSON序列化怎么算:从数据结构到字节流的转换艺术
什么是JSON序列化?——给数据“穿上一件统一的衣服”
在计算机世界里,数据在不同组件间传递时,常常需要“统一着装”,Python中的字典、Java中的对象、JavaScript中的数组,这些数据结构在内存中存储的方式千差万别:Python字典用哈希表实现,Java对象有属性和方法,JavaScript数组支持动态类型,要让它们在网络上传输、或在不同程序间共享,就必须转换成一种“通用语言”——这就是JSON序列化的核心任务。
JSON序列化是将内存中的数据结构(如对象、字典、列表等)转换为JSON格式字符串的过程,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以“键值对”或“值列表”的形式组织数据,结构简单、可读性强,已成为前后端交互、配置文件存储等场景的“事实标准”。
JSON序列化的“算法规程”:从内存到字符串的4步转换
JSON序列化看似简单(比如把Python的{"name": "Alice", "age": 30}变成字符串'{"name": "Alice", "age": 30}'),但其背后有一套严谨的转换规则,我们可以将其拆解为4个核心步骤:
第1步:遍历数据结构,识别“可序列化”的成员
序列化不是“无差别转换”,它只处理特定类型的数据,不同编程语言对“可序列化类型”的定义略有差异,但通常包括:
- 基本类型:字符串(String)、数字(Number,包括整数和浮点数)、布尔值(Boolean)、
null; - 复合类型:列表(List/Array)、字典(Dictionary/Object)。
遇到不可序列化的类型(如Python的函数、Java的文件对象、JavaScript的Symbol),序列化会直接报错或跳过(具体取决于语言实现),Python的json模块无法序列化lambda函数,会抛出TypeError。
第2步:按照JSON规范,构建“键值对”或“值列表”结构
JSON的核心语法只有两种:
- 对象(Object):无序的键值对集合,键必须是字符串,值可以是任意JSON支持的类型;用花括号包裹,键值对用逗号分隔,键和值用冒号连接(如
{"key": "value"})。 - 数组(Array):有序的值列表,值可以是任意JSON支持的类型;用方括号
[]包裹,元素用逗号分隔(如[1, "a", true])。
序列化时,会根据数据结构的类型“套用”这两种模板:
- Python的字典(
dict)→ JSON对象():字典的键会自动转为字符串(即使原键是数字,如{1: "one"}会变成{"1": "one"}),值递归处理; - Python的列表(
list)/元组(tuple)→ JSON数组([]):元组会被当作列表处理,元素按顺序递归转换; - Java的
Map→ JSON对象,List→ JSON数组,普通对象会通过反射提取字段名和字段值,转换为键值对。
第3步:处理数据类型“翻译”:从语言原生类型到JSON类型
这是序列化中最关键的“翻译”环节,不同编程语言的原生类型与JSON类型并非一一对应,需要严格转换:
| 编程语言原生类型 | JSON类型 | 示例 |
|---|---|---|
| 字符串(String) | 字符串(String) | "Hello" → "Hello" |
| 整数(int)/浮点数(float) | 数字(Number) | 123 → 123,14 → 14 |
| 布尔值(true/false) | 布尔值(Boolean) | True → true |
| null/None | null | None → null |
| 数组(Array/List) | 数组(Array) | [1, 2, 3] → [1, 2, 3] |
| 对象(Object/Dict) | 对象(Object) | {"a": 1} → {"a": 1} |
特殊注意:
- 数字类型:JSON不区分整数和浮点数,
1和0在JSON中都是数字,但序列化时会保留原始数值(如Python的1会变成1,0会变成0); - 字符串:JSON字符串必须用双引号包裹,单引号是非法的(如
'name'会被转为"name"); - 特殊字符:字符串中的换行符
\n、引号、反斜杠\等需要转义(如"He said \"Hi\""→"He said \"Hi\"")。
第4步:生成字符串,完成“编码”
将构建好的JSON结构拼接成字符串,并进行编码(通常是UTF-8),Python的{"name": "Alice", "age": 30}经过上述步骤,会生成字符串'{"name": "Alice", "age": 30}'(注意:Python的json模块默认会输出双引号,且字符串是Unicode编码)。
反序列化:逆向操作,让字符串“活”起来
与序列化相对的是反序列化(Deserialization),即把JSON字符串还原为编程语言原生数据结构,过程是序列化的“逆运算”:
- 解析字符串:读取JSON字符串,验证语法是否正确(如括号匹配、引号成对等);
- 构建数据结构:根据JSON的或
[],创建对应的字典/对象、列表/数组; - 类型转换:将JSON的字符串、数字、布尔值等还原为语言原生类型(如
"123"→123(整数),"true"→True(布尔值))。
JSON字符串'{"name": "Bob", "hobbies": ["reading", "coding"]}'在Python中反序列化后,会变成字典{"name": "Bob", "hobbies": ["reading", "coding"]}。
序列化的“边界问题”:什么情况下会“算错”?
JSON序列化并非万能,处理不当会引发问题,常见的“坑”包括:
循环引用:无限递归的“死循环”
如果数据结构中存在循环引用(如Python中,列表的第一个元素是列表自身),序列化时会陷入无限递归,最终导致栈溢出。
a = [] a.append(a) # 列表a包含自身 json.dumps(a) # 抛出RecursionError
解决方法:手动断开循环引用,或使用语言提供的循环引用处理机制(如Python的default参数自定义序列化逻辑)。
数据类型丢失:精度或类型信息丢失
JSON没有日期类型、时间类型、自定义类等,序列化时这些类型会被转为字符串或数字,反序列化时可能丢失信息。
- Python的
datetime对象序列化后变成字符串(如"2023-10-01T12:00:00"),反序列化时需手动转回datetime; - Java的
BigDecimal序列化为数字后,反序列化可能丢失精度(如456可能被转为456000...或45)。
特殊字符处理不当:引号、换行符的“转义陷阱”
JSON字符串中的双引号必须转义为\",否则会破坏字符串结构,字符串"He said: "Hi""序列化后应为"He said: \"Hi\"",若未转义,解析时会报错,换行符\n也需要转义为\\n,否则会被视为换行。
实战:不同语言的JSON序列化实现
Python:json模块的“标准化操作”
import json
# 原生数据结构
data = {
"name": "Alice",
"age": 30,
"is_student": False,
"courses": ["Math", "Science"],
"info": None
}
# 序列化
json_str = json.dumps(data, ensure_ascii=False) # ensure_ascii=False支持中文
print(json_str)
# 输出: {"name": "Alice", "age": 30, "is_student": false


还没有评论,来说两句吧...