前言
在日常开发中,JSON(JavaScript Object Notation)是数据交换最常用的格式之一。Python 内置的json模块提供了完整的 JSON 与 Python 数据类型之间的转换能力。本文将系统总结JSON 字符串 ↔ Python 字典/列表的相互转换知识,帮助你彻底掌握这一技能。
一、核心对应关系
理解类型映射是掌握转换的关键:
| JSON 类型 | Python 类型 |
|---|---|
object{} | dict(字典) |
array[] | list(列表) |
string"..." | str(字符串) |
| number(整数) | int |
| number(小数) | float |
true/false | True / False |
null | None |
重要规律:
JSON 的对象对应 Python 的字典
JSON 的数组对应 Python 的列表
Python 的字典/列表互相嵌套时,转换后依然是嵌套结构
二、四个核心函数
json模块中最常用的四个函数,记住一句话:
带
s的操作字符串,不带s的操作文件。
| 函数 | 方向 | 输入 | 输出 |
|---|---|---|---|
json.loads() | JSON → Python | 字符串 | dict / list |
json.dumps() | Python → JSON | dict / list | 字符串 |
json.load() | JSON → Python | 文件对象 | dict / list |
json.dump() | Python → JSON | dict / list | 写入文件 |
三、JSON 字符串 → 字典 / 列表
3.1 JSON 对象转字典
python
import json json_str = '{"name": "小明", "age": 18, "city": "北京"}' result = json.loads(json_str) print(result) print(type(result))输出:
text
{'name': '小明', 'age': 18, 'city': '北京'} <class 'dict'>3.2 JSON 数组转列表
python
import json json_str = '[1, 2, 3, "hello", true, null]' result = json.loads(json_str) print(result) print(type(result))输出:
text
[1, 2, 3, 'hello', True, None] <class 'list'>3.3 嵌套结构转换
python
import json json_str = ''' { "users": [ {"name": "小明", "age": 18}, {"name": "小红", "age": 20} ], "total": 2 } ''' result = json.loads(json_str) print(result["users"][0]["name"]) # 小明 print(result["total"]) # 2嵌套结构会按照对应关系逐层转换。
四、字典 / 列表 → JSON 字符串
4.1 字典转 JSON
python
import json data = {"name": "小明", "age": 18, "city": "北京"} json_str = json.dumps(data, ensure_ascii=False) print(json_str) print(type(json_str))输出:
text {"name": "小明", "age": 18, "city": "北京"} <class 'str'>4.2 列表转 JSON
python
import json data = [1, 2, 3, "hello", True, None] json_str = json.dumps(data, ensure_ascii=False) print(json_str) '''输出:''' text [1, 2, 3, "hello", true, null]注意:Python 的
True/False/None会变成 JSON 的true/false/null。
4.3 嵌套结构转换
python
import json data = { "users": [ {"name": "小明", "age": 18}, {"name": "小红", "age": 20} ], "total": 2 } json_str = json.dumps(data, ensure_ascii=False, indent=2) print(json_str)输出:
json { "users": [ { "name": "小明", "age": 18 }, { "name": "小红", "age": 20 } ], "total": 2 }五、dumps 常用参数详解
json.dumps()支持多个实用参数,掌握它们能让输出更符合需求。
5.1 ensure_ascii
控制非 ASCII 字符是否转义。
python
data = {"city": "北京"} # 默认 True,中文被转义 print(json.dumps(data)) # {"city": "\u5317\u4eac"} # 设为 False,中文原样输出(推荐) print(json.dumps(data, ensure_ascii=False)) # {"city": "北京"}建议:只要包含中文,都加上ensure_ascii=False。
5.2 indent
美化输出,设置缩进空格数。
python
data = {"name": "小明", "age": 18} print(json.dumps(data, ensure_ascii=False, indent=2))输出:
json
{ "name": "小明", "age": 18 }indent=None(默认)时输出为紧凑的一行。
5.3 sort_keys
按键名排序输出。
python
data = {"c": 3, "a": 1, "b": 2} print(json.dumps(data, sort_keys=True)) # {"a": 1, "b": 2, "c": 3}5.4 separators
自定义分隔符,用于压缩输出。
python
data = {"a": 1, "b": 2} # 默认: (', ', ': ') # 压缩: (',', ':') print(json.dumps(data, separators=(',', ':'))) # {"a":1,"b":2}5.5 参数速查表
| 参数 | 说明 | 常用值 |
|---|---|---|
ensure_ascii | 是否转义非 ASCII 字符 | False(中文场景) |
indent | 缩进空格数 | 2或4 |
sort_keys | 按键排序 | True/False |
separators | 分隔符 | (',', ':') |
default | 处理无法序列化的对象 | 自定义函数 |
六、文件读写操作
处理文件时用json.load()和json.dump()(不带 s)。
6.1 从文件读取 JSON
python
import json with open("data.json", "r", encoding="utf-8") as f: data = json.load(f) print(data) print(type(data))6.2 写入 JSON 到文件
python
import json data = {"name": "小明", "age": 18, "hobbies": ["读书", "游泳"]} with open("data.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2)务必指定
encoding="utf-8",否则中文可能乱码。
七、进阶技巧
7.1 处理特殊类型(如 datetime)
JSON 默认不支持日期、自定义对象等类型,可通过default参数处理。
python
import json from datetime import datetime def default_handler(obj): if isinstance(obj, datetime): return obj.strftime("%Y-%m-%d %H:%M:%S") raise TypeError(f"无法序列化: {type(obj)}") data = {"time": datetime.now()} print(json.dumps(data, default=default_handler, ensure_ascii=False)) # {"time": "2024-01-01 12:00:00"}7.2 object_hook 自定义解析
json.loads()支持object_hook,可在解析时对字典做处理。
python
import json def hook(d): if "age" in d: d["age"] = int(d["age"]) return d json_str = '{"name": "小明", "age": "18"}' result = json.loads(json_str, object_hook=hook) print(result) # {'name': '小明', 'age': 18}7.3 深拷贝的替代用法
利用 JSON 转换可以实现简单的深拷贝(仅限基础类型):
python
import json original = {"a": [1, 2, 3], "b": {"c": 4}} copy = json.loads(json.dumps(original)) copy["a"].append(4) print(original["a"]) # [1, 2, 3] 原数据不受影响 print(copy["a"]) # [1, 2, 3, 4]7.4 判断字符串是否为合法 JSON
python
import json def is_valid_json(s): try: json.loads(s) return True except json.JSONDecodeError: return False print(is_valid_json('{"a": 1}')) # True print(is_valid_json('{a: 1}')) # False八、常见错误与注意事项
8.1 单引号不是合法 JSON
JSON 标准要求字符串和键名使用双引号。
python
import json # 错误:单引号 json.loads("{'name': '小明'}") # json.decoder.JSONDecodeError # 正确:双引号 json.loads('{"name": "小明"}')8.2 尾随逗号不合法
python
# 错误 json.loads('{"a": 1, "b": 2,}') # 正确 json.loads('{"a": 1, "b": 2}')8.3 元组会被转为列表
python
import json data = (1, 2, 3) print(json.dumps(data)) # [1, 2, 3] print(type(json.loads("[1,2,3]"))) # <class 'list'>8.4 字典的键必须是字符串
JSON 对象的键必须是字符串,非字符串键会被转换。
python
import json data = {1: "a", 2: "b"} print(json.dumps(data)) # {"1": "a", "2": "b"}8.5 精度丢失问题
浮点数在转换中可能出现精度问题,涉及金额等高精度场景建议用字符串传输。
8.6 异常处理
python
import json try: data = json.loads('{"a": 1}') except json.JSONDecodeError as e: print(f"解析失败: {e}")九、完整示例:综合运用
python
import json # 原始 Python 数据(字典 + 列表嵌套) data = { "class": "三年二班", "students": [ {"name": "小明", "age": 18, "scores": [90, 85, 88]}, {"name": "小红", "age": 20, "scores": [95, 92, 98]} ], "count": 2 } # 1. 转换为 JSON 字符串 json_str = json.dumps(data, ensure_ascii=False, indent=2) print("=== JSON 字符串 ===") print(json_str) # 2. 保存到文件 with open("students.json", "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False, indent=2) # 3. 从文件读取 with open("students.json", "r", encoding="utf-8") as f: loaded = json.load(f) # 4. 访问数据 print("\n=== 访问数据 ===") print(loaded["class"]) for s in loaded["students"]: print(f'{s["name"]} 平均分: {sum(s["scores"]) / len(s["scores"]):.2f}')十、总结
核心口诀
JSON 对象 ↔ dict,JSON 数组 ↔ list
带
s操作字符串,不带s操作文件load是解析(JSON→Python),dump是序列化(Python→JSON)中文场景记得加
ensure_ascii=False文件读写记得指定
encoding="utf-8"
转换方向速查
| 需求 | 使用函数 |
|---|---|
| JSON 字符串 → 字典/列表 | json.loads() |
| 字典/列表 → JSON 字符串 | json.dumps() |
| JSON 文件 → 字典/列表 | json.load() |
| 字典/列表 → JSON 文件 | json.dump() |
掌握以上内容,基本可以应对 Python 开发中 99% 的 JSON 转换场景。如果涉及超大文件、高精度数值或高性能需求,可以考虑orjson、ujson等第三方库作为补充。
如果本文对你有帮助,欢迎点赞、收藏、评论三连支持一下!🎉