← 返回题目列表

Python 如何正确读写 JSON?json.dump、dumps、load、loads 有什么区别?

高频 简单 第 2 / 27 题 更新于 2026/07/31
JSONjson模块序列化文件读写

简化版

json.dumps() 把 Python 对象转成 JSON 字符串,json.dump() 把对象写入文件;json.loads() 从 JSON 字符串解析对象,json.load() 从文件读取并解析。读写中文时常用 ensure_ascii=False,文件编码建议显式指定 encoding="utf-8"

详细版

四个 API 的区别看名字:带 s 的处理 string,不带 s 的处理 file object。

import json

text = json.dumps({"name": "张三"}, ensure_ascii=False)
data = json.loads(text)

with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)

JSON 只支持有限类型:对象、数组、字符串、数字、布尔值和 null。datetimeDecimal、自定义对象默认不能直接序列化,需要转换或自定义 encoder。

完整版教学

一、为什么 JSON 是面试高频

JSON 是 Web API、配置文件、日志交换、前后端通信中最常见的数据格式之一。Python 项目里经常需要把 dict/list 写成 JSON,或从接口响应中解析 JSON。

Python dict/list <-> JSON text <-> 文件/API/消息

它看起来简单,但中文编码、日期、Decimal、浮点精度、大文件读取都容易踩坑。

二、dump 和 dumps 的区别

dumpss 表示 string,返回 JSON 字符串;dump 写入文件对象,不返回完整字符串。

obj = {"id": 1}
json_text = json.dumps(obj)

with open("a.json", "w", encoding="utf-8") as f:
    json.dump(obj, f)
API输入输出
dumpsPython 对象JSON 字符串
dumpPython 对象 + 文件写文件
loadsJSON 字符串Python 对象
load文件Python 对象

记住“s = string”,基本不会混。

三、中文为什么会变成转义

默认 ensure_ascii=True,非 ASCII 字符会变成 \uXXXX 转义。这样兼容性好,但人读文件不友好。写中文配置或日志时常用 ensure_ascii=False

json.dumps({"name": "张三"})
# {"name": "\u5f20\u4e09"}

json.dumps({"name": "张三"}, ensure_ascii=False)
# {"name": "张三"}

同时文件要显式指定 UTF-8,否则在不同系统默认编码下可能出错。

中文 JSON 的稳妥组合是 encoding="utf-8" + ensure_ascii=False

四、哪些对象不能直接序列化

JSON 标准没有 datetime、Decimal、set、自定义对象。Python 的 json 模块遇到这些类型会抛 TypeError

from datetime import datetime
json.dumps({"time": datetime.now()})  # TypeError

常见做法是先转换:

json.dumps({"time": datetime.now().isoformat()})

或提供 default 函数,把无法序列化的对象转成字符串、数字或 dict。

五、浮点数和 Decimal 的边界

JSON 数字没有区分 Python 的 floatDecimal。如果金融金额用 float 序列化再解析,可能带来精度问题。金额通常用字符串或整数分保存。

19.99 元 -> 1999 分

如果必须保留 Decimal,可以在序列化时转字符串,读取后再转回 Decimal。API 契约要明确字段类型,否则调用方会误用。

六、大 JSON 文件要注意什么

json.load(f) 会把整个 JSON 解析进内存。100MB 文件可能占用远超 100MB 的内存,因为 Python 对象有额外开销。如果是 JSON Lines,每行一个 JSON,可以逐行处理。

with open("data.jsonl", encoding="utf-8") as f:
    for line in f:
        obj = json.loads(line)
        handle(obj)

大数组 JSON 需要流式解析库,标准库不太适合超大 JSON 全量解析。

七、常见误区与追问

  • 误区:dump 和 dumps 一样。 dumps 返回字符串,dump 写文件。
  • 误区:JSON 能保存任意 Python 对象。 datetime、set、自定义对象默认不能直接序列化。
  • 误区:中文转义是乱码。 \uXXXX 是合法 JSON 转义,不是乱码,只是可读性差。
  • 追问:如何漂亮格式化?indent=2,必要时配合 sort_keys=True
  • 追问:金额字段怎么保存? 用整数分或字符串,避免 float 精度问题。
  • 追问:大文件怎么读? JSON Lines 可逐行读;大数组要考虑流式解析库。
  • 追问:接口返回 JSON 解析失败怎么办? 捕获 json.JSONDecodeError 并记录原始响应片段。

八、加强记忆

JSON 四个函数记住“有 s 处理字符串,无 s 处理文件”。中文用 UTF-8 和 ensure_ascii=False,特殊对象先转换,大文件别一口吞,金额别随手 float。面试里把 API 区别、编码、类型边界和大文件处理一起讲,就够完整。