json模块 — JSON编码解码

Python标准库精讲专题 · 数据持久化篇 · 掌握JSON数据处理

专题:Python标准库精讲系统学习

关键词:Python, 标准库, json, JSON, dumps, loads, dump, load, JSONEncoder, JSONDecoder, 序列化

一、JSON格式概述

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,广泛用于Web应用、配置文件、API通信等场景。Python的json模块提供了完整的JSON编码(序列化)和解码(反序列化)功能,能够在Python对象和JSON字符串之间灵活转换。

理解Python数据类型与JSON数据类型的对应关系,是正确使用json模块的基础。下表列出了二者之间的标准映射规则:

Python类型 JSON类型 示例 说明
dict object {"key": "value"} 键必须为字符串类型
list, tuple array [1, 2, 3] tuple编码后变为list
str string "hello" 必须使用双引号
int, float, int子类 number 42, 3.14 float('inf')会引发异常
True / False true / false true, false 注意大小写差异
None null null Python中的None直接映射
Decimal 不支持原生 需自定义编码器 默认会报TypeError
datetime 不支持原生 需自定义编码器 通常转为ISO格式字符串

从表中可以看出,Python的基本数据类型(dict、list、str、int、float、bool、None)可以与JSON自然对应,但Decimal、datetime、自定义类等类型则需要额外处理——这正是后续章节自定义编码器要解决的问题。

核心认知:JSON格式本身仅支持有限的数据类型,所有复杂Python对象都必须"降维"为这些基本类型的组合才能完成序列化。理解这个约束,就能理解为什么需要自定义编码器。

二、核心编码函数

json模块提供了两个核心编码函数:json.dumps()用于将Python对象转换为JSON字符串,json.dump()用于将Python对象直接写入文件流。二者在参数上完全一致,区别仅在于输出目标不同。

2.1 json.dumps() 参数详解

json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) 是JSON序列化的核心函数。以下逐一讲解最常用的参数及其实战用法:

sort_keys — 排序输出

设置sort_keys=True可以让输出JSON的键按字母顺序排列。这在版本控制对比、缓存键生成等场景中非常有用,能够保证相同内容始终产生相同的输出顺序。

import json data = {"name": "Alice", "age": 30, "role": "admin"} result = json.dumps(data, sort_keys=True, indent=2) print(result) # 输出: # { # "age": 30, # "name": "Alice", # "role": "admin" # }

indent — 格式化缩进

indent参数控制输出的缩进空格数,使JSON对人类可读。indent=2使用2个空格缩进,indent=4使用4个空格缩进。该参数在调试日志、配置文件生成场景中不可或缺。

# indent为None(默认)时输出紧凑格式 print(json.dumps({"a": 1, "b": 2})) # 输出:{"a": 1, "b": 2} # indent=2输出格式化格式 print(json.dumps({"a": 1, "b": 2}, indent=2)) # 输出: # { # "a": 1, # "b": 2 # }

separators — 紧凑控制

separators参数接受一个二元组(item_separator, key_separator),用于控制输出中各项之间的分隔符。默认值为(', ', ': '),可通过设置为(',', ':')来移除多余空格,生成最小体积的JSON,适用于网络传输场景。

data = {"name": "Bob", "scores": [90, 85, 92]} compact = json.dumps(data, separators=(',', ':')) print(compact) # 输出:{"name":"Bob","scores":[90,85,92]} # 对比默认输出 default = json.dumps(data) print(default) # 输出:{"name": "Bob", "scores": [90, 85, 92]}

ensure_ascii — ASCII转义控制

ensure_ascii参数控制非ASCII字符(如中文)的处理方式。默认为True,会将所有非ASCII字符转义为\\uXXXX形式。设置为False时,保留原字符,使JSON内容可读性大幅提升。此参数在中文处理章节会详细展开。

data = {"message": "你好世界"} print(json.dumps(data)) # 输出:{"message": "\\u4f60\\u597d\\u4e16\\u754c"} print(json.dumps(data, ensure_ascii=False)) # 输出:{"message": "你好世界"}

skipkeys — 键类型容错

默认情况下,如果字典键不是基本类型(str、int、float、bool、None),json.dumps会抛出TypeError。设置skipkeys=True可以跳过这些非标准键,而不是抛出异常。这在处理混合类型键的字典时非常实用。

data = {("tuple_key",): "value", "normal_key": 42} # 默认行为:TypeError: keys must be str, int, float, bool or None # 使用skipkeys跳过不可序列化的键 result = json.dumps(data, skipkeys=True) print(result) # 输出:{"normal_key": 42}

default — 兜底序列化函数

default参数接受一个函数,当json模块遇到无法序列化的对象时,会调用此函数进行处理。该函数接收无法序列化的对象,应返回一个可序列化的表示形式。这是快速处理自定义类型的最简便方式。

from datetime import datetime def custom_serializer(obj): if isinstance(obj, datetime): return obj.isoformat() raise TypeError(f"Type {type(obj)} not serializable") now = datetime.now() data = {"event": "meeting", "time": now} result = json.dumps(data, default=custom_serializer) print(result) # 输出示例:{"event": "meeting", "time": "2026-05-05T23:56:48.123456"}

2.2 json.dump() — 写入文件流

json.dump()用于将Python对象直接序列化并写入文件对象。其参数与dumps()完全一致,区别在于第一个参数之后需要传入一个可写的文件对象。务必确保文件以文本模式打开并指定正确的编码。

import json data = {"name": "配置文件", "version": "2.0", "debug": False} # 写入JSON文件 with open("config.json", "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) # 读取验证 with open("config.json", "r", encoding="utf-8") as f: loaded = json.load(f) print(loaded) # 输出:{"name": "配置文件", "version": "2.0", "debug": False}

注意:使用dump写入文件时,必须显式指定encoding="utf-8"(Python 3默认已使用UTF-8,但显式指定是良好实践)。另外注意使用w模式而非wb模式——JSON是文本格式,不应以二进制模式写入。

三、核心解码函数

json模块提供了两个核心解码函数:json.loads()用于将JSON字符串解析为Python对象,json.load()用于从文件流中读取并解析JSON数据。二者参数基本一致,可以处理相同的JSON格式选项。

3.1 json.loads() — 解析字符串

json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) 是最常用的解码函数。它将JSON字符串严格解析为对应的Python对象,默认情况下不接受单引号、注释等非标准JSON格式。

import json # 基本用法 json_str = '{"name": "Alice", "age": 30, "scores": [95, 87, 92]}' data = json.loads(json_str) print(data) # 输出:{"name": "Alice", "age": 30, "scores": [95, 87, 92]} print(type(data)) # 输出: # 数组解析为列表 arr_str = '[1, 2, 3, "four", true, null]' arr = json.loads(arr_str) print(arr) # 输出:[1, 2, 3, "four", True, None]

严格性:json.loads遵循严格的JSON规范(RFC 7159),不支持Python字面量语法中的单引号、尾随逗号、注释等扩展语法。如果需要解析更宽松的格式,可以考虑使用ast.literal_eval或第三方库(如demjson)。

# 以下用法会引发异常: # json.loads("{'name': 'Alice'}") # SyntaxError: 单引号不被允许 # json.loads('{"name": "Alice",}') # SyntaxError: 尾随逗号不被允许 # json.loads('{"name": /*comment*/ "Alice"}') # SyntaxError: 注释不被允许

3.2 json.load() — 从文件流读取

json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) 从文件对象中读取JSON数据并解析。它是对loads的封装,内部会自动读取文件内容再调用loads。务必以文本模式打开文件。

import json # 准备示例文件 data = {"projects": [{"id": 1, "name": "Alpha"}, {"id": 2, "name": "Beta"}]} with open("projects.json", "w", encoding="utf-8") as f: json.dump(data, f, indent=2) # 从文件加载 with open("projects.json", "r", encoding="utf-8") as f: loaded = json.load(f) print(loaded["projects"][0]["name"]) # 输出:Alpha

性能要点:对于大文件(数百MB以上),load()会将整个文件读入内存再解析,可能占用大量内存。如需处理超大JSON文件,建议使用ijson等流式解析库,可以逐层解析而不将全部数据加载到内存中。

3.3 解析钩子函数

loads和load支持parse_float、parse_int、parse_constant三个参数,用于拦截JSON基本类型的解析过程。这在需要特殊数字精度控制(如将浮点数全部解析为Decimal)的场景中非常实用。

from decimal import Decimal json_str = '{"price": 19.99, "quantity": 100, "large": 1e20}' data = json.loads( json_str, parse_float=Decimal, parse_int=lambda x: int(x) * 2 # 整数翻倍 ) print(data["price"], type(data["price"])) # 输出:19.99 print(data["quantity"], data["large"]) # 输出:200 1E+20

四、自定义编码器

当默认的json.dumps无法处理自定义Python对象时,我们需要创建JSONEncoder的子类并覆盖default()方法。这是官方推荐的自定义序列化方案,具有可复用、封装性好、与框架集成度高等优点。

4.1 基础自定义编码器

继承json.JSONEncoder并实现default(self, o)方法,该方法接收一个无法被默认编码器处理的对象o,应返回一个可被JSON序列化的Python对象。如果仍无法处理,则应调用super().default(o)以触发默认的TypeError异常。

import json from datetime import datetime, date from decimal import Decimal class CustomEncoder(json.JSONEncoder): """支持datetime、date、Decimal的自定义JSON编码器""" def default(self, o): if isinstance(o, datetime): return o.strftime("%Y-%m-%d %H:%M:%S") if isinstance(o, date): return o.isoformat() if isinstance(o, Decimal): return float(o) # 注意:可能有精度损失 if isinstance(o, set): return list(o) if isinstance(o, bytes): return o.decode("utf-8", errors="replace") return super().default(o) # 使用自定义编码器 data = { "name": "事件记录", "created_at": datetime.now(), "event_date": date(2026, 5, 5), "score": Decimal("99.95"), "tags": {"urgent", "important"}, "raw": b"hello bytes" } # 方式一:通过cls参数传入 result = json.dumps(data, cls=CustomEncoder, indent=2, ensure_ascii=False) print(result) # 输出: # { # "name": "事件记录", # "created_at": "2026-05-05 23:56:48", # "event_date": "2026-05-05", # "score": 99.95, # "tags": ["urgent", "important"], # "raw": "hello bytes" # }

4.2 使用inheritence链式编码

在某些复杂场景中,需要将多种自定义编码器组合使用。可以通过Mixin或继承链的方式实现编码器的复用。下面展示一个结合了多种特殊类型支持的编码器:

import json from pathlib import Path from uuid import UUID class AdvancedEncoder(json.JSONEncoder): """支持更多Python特殊类型的编码器""" def default(self, o): if isinstance(o, UUID): return str(o) if isinstance(o, Path): return str(o.as_posix()) if isinstance(o, complex): return {"real": o.real, "imag": o.imag} if isinstance(o, range): return list(o) if isinstance(o, frozenset): return list(o) if isinstance(o, Exception): return {"type": type(o).__name__, "args": o.args} # 尝试调用对象的to_dict方法(如果有) if hasattr(o, "to_dict") and callable(o.to_dict): return o.to_dict() return super().default(o) # 配合前面的CustomEncoder实现链式 class ChainEncoder(CustomEncoder, AdvancedEncoder): """组合两个编码器的能力""" pass # 测试 from uuid import uuid4 test_data = { "id": uuid4(), "path": Path("/usr/local/config"), "fp": frozenset([1, 2, 3]) } print(json.dumps(test_data, cls=ChainEncoder, indent=2)) # { # "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", # "path": "/usr/local/config", # "fp": [1, 2, 3] # }

4.3 迭代器与生成器编码

JSONEncoder默认支持list、tuple等序列类型,但无法直接处理迭代器和生成器。通过在default方法中处理这些类型,可以实现流式数据的编码:

class IterableEncoder(json.JSONEncoder): def default(self, o): try: if hasattr(o, "__iter__"): return list(o) except TypeError: pass return super().default(o) def number_generator(n): for i in range(n): yield i data = {"numbers": number_generator(5)} result = json.dumps(data, cls=IterableEncoder) print(result) # 输出:{"numbers": [0, 1, 2, 3, 4]}

最佳实践:自定义JSONEncoder通常比使用dumps的default参数更可取。原因有三:一是编码器可复用,一处定义到处使用;二是子类可以覆盖iterencode等方法实现更细粒度的控制;三是与Flask、Django等框架的jsonify集成更自然。

五、自定义解码器

与编码对应,json模块也提供了自定义解码的机制。通过继承JSONDecoder或利用object_hook参数,可以控制JSON数据反序列化为Python对象的过程,实现从普通字典到自定义类实例的转换。

5.1 object_hook — 字典到对象的转换

object_hook是loads/load函数的一个参数,接受一个可调用对象。在解析过程中,每当遇到JSON对象(即Python字典)时,都会先解析为dict,然后自动调用object_hook函数进行处理。这是将JSON数据转换回自定义类实例的最简方式。

import json class Person: def __init__(self, name, age, role): self.name = name self.age = age self.role = role def __repr__(self): return f"Person(name={self.name!r}, age={self.age}, role={self.role!r})" def person_hook(dct): """将带有type标记的字典转换为Person实例""" if "type" in dct and dct["type"] == "Person": return Person( name=dct.get("name", ""), age=dct.get("age", 0), role=dct.get("role", "user") ) return dct # 其他字典原样返回 json_str = ''' { "type": "Person", "name": "Charlie", "age": 28, "role": "developer" } ''' person = json.loads(json_str, object_hook=person_hook) print(person) # 输出:Person(name='Charlie', age=28, role='developer') print(type(person)) # 输出:

5.2 object_pairs_hook — 保留键顺序

object_pairs_hook与object_hook类似,但传入的是有序的键值对列表而非字典。这对于需要保留JSON对象键顺序、处理重复键或创建OrderedDict等场景非常有用。注意object_pairs_hook的优先级高于object_hook。

import json from collections import OrderedDict json_str = '{"b": 1, "a": 2, "c": 3}' # 使用object_pairs_hook创建OrderedDict result = json.loads(json_str, object_pairs_hook=OrderedDict) print(list(result.keys())) # 输出:['b', 'a', 'c'] —— 保留了JSON中的原始顺序 # 处理重复键(JSON规范不推荐,但实际数据可能存在) duplicate_json = '{"key": "first", "key": "second"}' def collect_pairs(pairs): """收集重复键的所有值""" result = OrderedDict() for k, v in pairs: if k in result: if not isinstance(result[k], list): result[k] = [result[k]] result[k].append(v) else: result[k] = v return result parsed = json.loads(duplicate_json, object_pairs_hook=collect_pairs) print(parsed) # 输出:OrderedDict([('key', ['first', 'second'])])

5.3 JSONDecoder子类定制

更正式的自定义解码方案是继承JSONDecoder并覆盖相关方法。这种方式在框架集成和复杂解码逻辑中更常用。

import json from datetime import datetime class CustomDecoder(json.JSONDecoder): """支持ISO格式日期字符串自动转为datetime的自定义解码器""" def __init__(self, *args, **kwargs): super().__init__( *args, **kwargs, object_hook=self._object_hook ) @staticmethod def _object_hook(dct): """递归处理字典中的值,将ISO日期字符串转为datetime""" for key, value in dct.items(): if isinstance(value, str): # 尝试解析ISO格式日期 try: dct[key] = datetime.fromisoformat(value) except (ValueError, TypeError): pass elif isinstance(value, dict): dct[key] = CustomDecoder._object_hook(value) return dct # 使用自定义解码器 json_str = '''{ "title": "会议", "start": "2026-05-05T14:30:00", "end": "2026-05-05T16:00:00", "location": {"name": "会议室A", "floor": 3} }''' data = json.loads(json_str, cls=CustomDecoder) print(data["start"], type(data["start"])) # 输出:2026-05-05 14:30:00 print(data["location"]["name"], type(data["location"]["name"])) # 输出:会议室A (非日期字符串不会被误转)

5.4 parse_float / parse_int 进阶用法

除了object_hook系列参数,parse_float和parse_int参数允许在更低层级拦截数字的解析过程。这在需要精确控制数字类型(如避免浮点精度问题)时非常强大。

from decimal import Decimal, ROUND_HALF_UP # 将所有JSON数字解析为Decimal,避免浮点精度问题 json_str = '{"total": 0.1, "tax": 0.2, "sum": 0.3}' # 默认行为 —— 浮点数精度问题 default = json.loads(json_str) print(default["total"] + default["tax"]) # 0.30000000000000004 # 使用Decimal解析 precise = json.loads( json_str, parse_float=Decimal, parse_int=Decimal ) print(precise["total"] + precise["tax"]) # 0.3 print(precise["total"] + precise["tax"] == precise["sum"]) # True

注意:object_hook的调用发生在字典构建完成之后,parse_float/parse_int的调用发生在JSON词法分析阶段。因此parse_float/parse_int对所有JSON数字生效,而object_hook仅对JSON对象(字典)生效。理解这一层次关系有助于选择正确的扩展点。

六、中文与特殊处理

在实际项目中,json模块最常遇到的三个特殊处理场景是:中文编码、日期时间序列化、Decimal数值精度。本节深入讲解这些场景的最佳实践方案。

6.1 中文处理 — ensure_ascii=False

默认情况下,json.dumps会将所有非ASCII字符(包括中文)转义为\\uXXXX形式的Unicode转义序列。这种输出的可读性极差,在调试、日志记录、数据交换等场景中都会带来困扰。设置ensure_ascii=False即可保留原始字符。

import json data = { "title": "Python json模块学习笔记", "author": "学习者", "tags": ["序列化", "编码解码", "数据处理"], "description": "本章详细讲解json模块的核心用法" } # 默认行为 default_output = json.dumps(data, indent=2) print(default_output) # 输出(不可读): # { # "title": "\\u0050\\u0079\\u0074\\u0068\\u006f\\u006e ......" # } # 正确做法 readable_output = json.dumps(data, indent=2, ensure_ascii=False) print(readable_output) # 输出(完全可读): # { # "title": "Python json模块学习笔记", # "author": "学习者", # "tags": ["序列化", "编码解码", "数据处理"], # "description": "本章详细讲解json模块的核心用法" # }

写入文件时的编码配合:使用ensure_ascii=False时,务必确保文件打开时指定了正确的编码,否则写入操作可能导致编码错误。

# 正确的文件写入方式 with open("notes.json", "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) # 错误的写入方式 —— 可能引发编码错误或乱码 # with open("notes.json", "w") as f: # 默认使用locale编码 # json.dump(data, f, indent=2, ensure_ascii=False)

6.2 日期时间序列化

Python的datetime、date、time等类型不是JSON原生支持的类型,需要转换为字符串后再序列化。常见的策略包括ISO格式字符串、时间戳、自定义格式。选择合适的方案取决于使用场景。

import json from datetime import datetime, date, time, timedelta # 方案一:ISO格式(推荐用于人类可读场景) def datetime_to_iso(obj): if isinstance(obj, (datetime, date)): return obj.isoformat() if isinstance(obj, time): return obj.isoformat(timespec="seconds") if isinstance(obj, timedelta): return obj.total_seconds() raise TypeError(f"Type {type(obj)} not serializable") data = { "event": "系统上线", "timestamp": datetime.now(), "launch_date": date(2026, 6, 1), "duration": timedelta(hours=2, minutes=30) } result = json.dumps(data, default=datetime_to_iso, indent=2, ensure_ascii=False) print(result) # 输出: # { # "event": "系统上线", # "timestamp": "2026-05-05T23:56:48.123456", # "launch_date": "2026-06-01", # "duration": 9000.0 # } # 方案二:时间戳(推荐用于机器处理、排序场景) def datetime_to_timestamp(obj): if isinstance(obj, datetime): return obj.timestamp() if isinstance(obj, date): return datetime(obj.year, obj.month, obj.day).timestamp() raise TypeError(f"Type {type(obj)} not serializable") result_ts = json.dumps( {"event": "start", "at": datetime.now()}, default=datetime_to_timestamp ) print(result_ts) # 输出:{"event": "start", "at": 1746467808.123456}

6.3 Decimal编码与精度控制

Decimal类型用于高精度数值计算(如金融、科学计算),但JSON不原生支持。常见的处理方式有三种:转为浮点数(有精度损失)、转为字符串(保留精度但失去数值类型)、使用自定义对象表示。

import json from decimal import Decimal, ROUND_HALF_UP # 方式一:转为float(可能导致精度损失) def decimal_to_float(obj): if isinstance(obj, Decimal): return float(obj) raise TypeError d = Decimal("19.99") print(json.dumps({"price": d}, default=decimal_to_float)) # 输出:{"price": 19.99} # 方式二:转为字符串(保留精度,但解码后是字符串) def decimal_to_str(obj): if isinstance(obj, Decimal): return str(obj) raise TypeError print(json.dumps({"price": d}, default=decimal_to_str)) # 输出:{"price": "19.99"} # 方式三:使用自定义标记对象(推荐,信息最完整) def decimal_to_marked(obj): if isinstance(obj, Decimal): return {"__type__": "Decimal", "value": str(obj)} raise TypeError print(json.dumps({"price": d}, default=decimal_to_marked, indent=2)) # 输出: # { # "price": { # "__type__": "Decimal", # "value": "19.99" # } # } # 配合自定义解码器还原 def decimal_decoder(dct): if "__type__" in dct and dct["__type__"] == "Decimal": return Decimal(dct["value"]) return dct encoded = json.dumps({"price": d}, default=decimal_to_marked) decoded = json.loads(encoded, object_hook=decimal_decoder) print(decoded["price"], type(decoded["price"])) # 输出:19.99 # 精度完全保留,可以进行精确计算

6.4 其他特殊类型处理

除上述常见场景外,实际项目中还可能遇到以下特殊类型的序列化需求:

import json import numpy as np from enum import Enum from pathlib import Path class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 class UniversalEncoder(json.JSONEncoder): """通用编码器,覆盖更多特殊类型""" def default(self, o): # Enum类型 if isinstance(o, Enum): return {"__enum__": type(o).__name__, "value": o.value} # numpy数值类型 if isinstance(o, (np.integer,)): return int(o) if isinstance(o, (np.floating,)): return float(o) if isinstance(o, np.ndarray): return o.tolist() # Path路径 if isinstance(o, Path): return str(o.as_posix()) # bytes if isinstance(o, bytes): return o.hex() # 正则表达式 import re if isinstance(o, re.Pattern): return {"__regex__": o.pattern, "flags": o.flags} return super().default(o) # 测试 import re data = { "color": Color.RED, "pattern": re.compile(r"\\d+\\.\\d+"), "binary": b"\\x00\\x01\\x02" } print(json.dumps(data, cls=UniversalEncoder, indent=2)) # 输出: # { # "color": {"__enum__": "Color", "value": 1}, # "pattern": {"__regex__": "\\d+\\.\\d+", "flags": 256}, # "binary": "000102" # }

七、核心总结

一、四大核心函数

json.dumps() —— Python对象转JSON字符串,序列化的核心入口

json.dump() —— Python对象直接序列化写入文件流

json.loads() —— JSON字符串解析为Python对象,反序列化核心入口

json.load() —— 从文件流读取并解析JSON数据

二、编码参数速记

sort_keys=True —— 键排序输出,保证一致性

indent=N —— 格式化缩进,提升可读性

separators=(',', ':') —— 紧凑输出,减少带宽

ensure_ascii=False —— 保留中文等非ASCII字符

skipkeys=True —— 跳过非标准键类型的容错模式

default=func —— 兜底序列化函数,处理不可序列化类型

三、自定义扩展机制

继承JSONEncoder + 覆盖default() —— 自定义序列化(推荐)

object_hook回调函数 —— 自定义反序列化字典到对象转换

object_pairs_hook —— 保留键顺序或处理重复键

parse_float/parse_int —— 低层级数字类型拦截

继承JSONDecoder —— 完整的自定义解码器方案

四、常见陷阱与最佳实践

写入文件务必指定encoding="utf-8",读取文件务必使用文本模式

Decimal序列化建议使用"标记对象"方案(如{"__type__":"Decimal","value":"..."})以无损保留精度

ensure_ascii=False与indent配合使用,可同时保证可读性和正确性

处理超大JSON文件时考虑ijson流式解析,避免内存溢出

网络传输场景建议设置separators=(',', ':')以最小化数据体积

JSON格式严格遵循RFC 7159,不支持单引号、注释、尾随逗号等Python风格写法

学习提示:json模块是Python标准库中"小而精"的典范。它的API设计清晰——四个函数构成核心,两个类支撑扩展。掌握json模块不仅是为了处理JSON数据,更能帮助理解"序列化协议"的设计思想:如何定义类型映射、如何提供扩展点、如何在严格与灵活之间取得平衡。这些思想同样适用于pickle、yaml、msgpack等其他序列化格式的学习。