Tutorial

Python JSON 实战指南:从 Datetime 序列化到流式读取大文件

详解 Python 中 json 模块的高阶用法:自定义 Encoder 处理日期时间、ensure_ascii 解决中文乱码、流式读取 GB 级 JSON,并对比 orjson/ujson 性能。

2026-04-085 min read

Python JSON 实战指南:从 Datetime 序列化到流式读取大文件

在 Python 开发里,JSON 几乎是后端接口、日志处理与数据交换的默认格式。看起来简单的 json.dumps() / json.loads(),一旦碰到日期时间、中文字符和大文件,就很容易出错或性能下降。

本文基于真实开发场景,整理一套可直接落地的实践方案,覆盖:

  • loads/dumpsload/dump 的正确使用边界
  • datetime 不能序列化的稳定解法
  • ensure_ascii=False 处理中文可读性
  • • 大文件流式读取策略(JSON Lines 与 ijson
  • orjson / ujson 的性能取舍


1) loads/dumpsload/dump 的区别

  • json.dumps(obj):Python 对象 -> JSON 字符串
  • json.loads(text):JSON 字符串 -> Python 对象
  • json.dump(obj, file):Python 对象 -> 写入文件
  • json.load(file):文件 -> Python 对象

简单记法:s 是字符串,不带 s 是文件


2) Datetime 序列化错误怎么处理

当对象里包含 datetime 时,直接序列化会报错:

from datetime import datetime
import json

json.dumps({"now": datetime.now()})
# TypeError: Object of type datetime is not JSON serializable

推荐方案是自定义 JSONEncoder

from datetime import datetime, date
import json

class DateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, date):
            return obj.isoformat()
        return super().default(obj)

payload = {"now": datetime.now(), "today": date.today()}
print(json.dumps(payload, cls=DateTimeEncoder, ensure_ascii=False, indent=2))

如果你希望固定格式(如 YYYY-MM-DD HH:MM:SS),可以把 isoformat() 替换为 strftime()


3) 中文变成 \uXXXX 的原因

默认情况下,json.dumps() 会转义非 ASCII 字符:

import json
print(json.dumps({"message": "你好,世界"}))
# {"message": "\u4f60\u597d\uff0c\u4e16\u754c"}

改成如下即可保持中文可读:

import json
print(json.dumps({"message": "你好,世界"}, ensure_ascii=False))

写文件时同时指定 encoding="utf-8"

with open("data.json", "w", encoding="utf-8") as f:
    json.dump({"message": "你好,世界"}, f, ensure_ascii=False)


4) 如何读取 GB 级 JSON 文件

一次性 json.load() 读大数组很容易占满内存。实践上有两条路线:

路线 A:优先使用 JSON Lines (.jsonl)

每行一条 JSON,天然适合流式处理:

import json

def read_jsonl(path):
    with open(path, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if line:
                yield json.loads(line)

for obj in read_jsonl("events.jsonl"):
    pass  # 逐条处理

路线 B:必须读取超大数组时用 ijson

pip install ijson

import ijson

def iter_huge_array(path):
    with open(path, "rb") as f:
        for item in ijson.items(f, "item"):
            yield item


5) 标准库 vs orjson / ujson

  • 标准库 json:稳定、零依赖、兼容性最好
  • orjson:性能通常更强,且对 datetime 支持友好
  • ujson:上手简单,性能也有提升,但边缘行为需验证

示例(orjson):

import orjson
from datetime import datetime

data = {"name": "Alice", "now": datetime.now()}
raw = orjson.dumps(data)   # bytes
obj = orjson.loads(raw)


6) 最佳实践清单

  1. 字符串场景用 loads/dumps,文件场景用 load/dump
  1. 涉及日期时间,统一封装 Encoder 或统一使用 orjson
  1. 面向中文内容默认开启 ensure_ascii=False
  1. 大体量日志优先设计成 JSON Lines
  1. 性能敏感路径做基准测试后再替换解析库


继续使用 JSON Work 在线工具

这套工具在浏览器本地运行,输入数据不会上传服务器,适合快速验证与调试 JSON。


参考资料

JSON Work 团队

致力于为开发者提供最佳的 JSON 处理工具

相关文章

更多文章即将发布...

返回博客

相关工具推荐

常见问题

关于跟进更新、选题方向与互动反馈。

如何第一时间看到新文章?

收藏本博客列表页,并在首页与工具聚合页留意指南入口。阅读文章无需注册或邮件订阅。

博客主要写什么?

围绕 JSON 校验、格式化、转换与调试流程,以及 JSON Work 工具更新,与在线工具的本地能力一一对应。

可以建议教程选题吗?

可以。请通过关于页的联系方式或 GitHub 反馈;我们会优先安排贴近真实开发场景的教程。

需要帮助?