← 返回博客

如何在 Python 中处理 JSON 数据

2026-04-20 · 5 分钟阅读

Python json 模块基础

Python 内置的 json 模块是处理 JSON 的标准方式,无需安装额外依赖。它提供四个核心函数:json.loads()(字符串 → Python 对象)、json.dumps()(Python 对象 → 字符串)、json.load()(文件 → Python 对象)、json.dump()(Python 对象 → 文件)。这四个函数名的 s 代表 string,有 s 的操作字符串,没有 s 的操作文件对象——记住这个规律就不会混淆。

Python 的 JSON 类型映射:JSON 对象({})↔ Python 字典(dict);JSON 数组([])↔ Python 列表(list);JSON 字符串 ↔ Python str;JSON 数字 ↔ Python intfloat;JSON true/false ↔ Python True/False;JSON null ↔ Python None

import json

# 字符串解析 / String parsing
json_str = '{"name": "Alice", "age": 30, "active": true}'
data = json.loads(json_str)
print(data['name'])    # "Alice"
print(data['active'])  # True (Python bool, not string)
print(type(data))      #

# 序列化为字符串 / Serialize to string
obj = {"name": "Bob", "scores": [95, 87, 92]}
json_str = json.dumps(obj)                          # 紧凑 / Compact
pretty_str = json.dumps(obj, indent=2)              # 格式化 / Pretty
sorted_str = json.dumps(obj, indent=2, sort_keys=True)  # 键排序 / Sorted keys
unicode_str = json.dumps(obj, ensure_ascii=False)   # 保留中文 / Preserve CJK

读写 JSON 文件

在 Python 中读写 JSON 文件是最常见的操作之一,使用 json.load()json.dump() 配合 open() 上下文管理器:

import json

# 读取 JSON 文件 / Reading JSON file
with open('data.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

# 写入 JSON 文件 / Writing JSON file
with open('output.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=2, ensure_ascii=False)

# 追加到 JSON Lines 文件(每行一个 JSON 对象)
# Append to JSON Lines file (one JSON object per line)
with open('data.jsonl', 'a', encoding='utf-8') as f:
    f.write(json.dumps(new_record, ensure_ascii=False) + '\n')

# 读取 JSON Lines 文件 / Reading JSON Lines file
records = []
with open('data.jsonl', 'r', encoding='utf-8') as f:
    for line in f:
        if line.strip():  # 跳过空行 / Skip empty lines
            records.append(json.loads(line))

自定义序列化:处理特殊类型

Python 的 json 模块默认不支持序列化 datetimeDecimalUUID、自定义类等类型。可以通过自定义 JSONEncoder 或提供 default 函数来扩展:

import json
from datetime import datetime, date
from decimal import Decimal
from uuid import UUID

# 方法 1:使用 default 函数 / Method 1: Using default function
def extended_encoder(obj):
    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    if isinstance(obj, Decimal):
        return float(obj)
    if isinstance(obj, UUID):
        return str(obj)
    if hasattr(obj, '__dict__'):
        return obj.__dict__
    raise TypeError(f'Object of type {type(obj)} is not JSON serializable')

json.dumps(data, default=extended_encoder)

# 方法 2:自定义 JSONEncoder / Method 2: Custom JSONEncoder
class ExtendedEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        if isinstance(obj, Decimal):
            return str(obj)  # 精确金额用字符串 / Precise amounts as string
        return super().default(obj)

json.dumps(data, cls=ExtendedEncoder, indent=2)

# 自定义解码(object_hook)/ Custom decoding (object_hook)
def datetime_decoder(dct):
    for key, value in dct.items():
        if isinstance(value, str) and 'T' in value:
            try:
                dct[key] = datetime.fromisoformat(value)
            except ValueError:
                pass
    return dct

data = json.loads(json_str, object_hook=datetime_decoder)

使用 Pydantic 进行 JSON 数据验证

Pydantic 是 Python 生态中最流行的数据验证库,通过类型注解定义数据模型,自动验证 JSON 数据的类型和格式,并提供清晰的错误信息。它在 FastAPI 中被广泛使用:

from pydantic import BaseModel, EmailStr, validator
from typing import Optional, List
from datetime import datetime

class Address(BaseModel):
    city: str
    country: str
    zip_code: Optional[str] = None

class User(BaseModel):
    id: int
    name: str
    email: str
    age: int
    address: Address
    tags: List[str] = []
    created_at: datetime

    @validator('age')
    def validate_age(cls, v):
        if v < 0 or v > 150:
            raise ValueError('Age must be between 0 and 150')
        return v

# 从 JSON 字符串解析并验证
# Parse and validate from JSON string
json_str = '''
{
  "id": 1,
  "name": "Alice",
  "email": "[email protected]",
  "age": 30,
  "address": {"city": "Beijing", "country": "China"},
  "created_at": "2025-01-01T00:00:00"
}
'''

user = User.model_validate_json(json_str)  # Pydantic v2
# 或 / or:
# user = User.parse_raw(json_str)  # Pydantic v1

# 序列化回 JSON
# Serialize back to JSON
print(user.model_dump_json(indent=2))

高性能 JSON 库:orjson

orjson 是 Python 性能最高的 JSON 库,用 Rust 实现,比标准 json 模块快 10 倍以上。它还原生支持 datetimeUUIDnumpy 数组等类型,是处理大量 JSON 数据或高吞吐量应用的首选:

# 安装 / Install
# pip install orjson

import orjson
from datetime import datetime
from uuid import UUID

# 基本用法与 json 模块类似 / Basic usage similar to json module
data = {'name': 'Alice', 'created': datetime.now(), 'id': UUID('...')}

# 序列化(返回 bytes,不是 str)
# Serialize (returns bytes, not str)
json_bytes = orjson.dumps(data)
json_bytes = orjson.dumps(data, option=orjson.OPT_INDENT_2)  # 格式化

# 反序列化(接受 str 或 bytes)
# Deserialize (accepts str or bytes)
data = orjson.loads(json_bytes)

# 性能对比(同等数据)/ Performance comparison (same data)
# json.dumps:  ~1000 µs
# orjson.dumps: ~80 µs  (约 12 倍速度 / ~12x faster)

# ujson 也是快速替代选项
# ujson is also a fast alternative option
# pip install ujson
import ujson
data = ujson.loads(json_str)
output = ujson.dumps(data, ensure_ascii=False, indent=2)

在 API 开发中处理 JSON

Python 中最流行的 API 框架 FastAPI 和 Flask 都内置了 JSON 支持。FastAPI(推荐用于新项目):基于 Pydantic 的自动 JSON 序列化/反序列化,自动生成 OpenAPI Schema;请求体自动解析为 Pydantic 模型,响应自动序列化:

# FastAPI 示例 / FastAPI example
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class UserCreate(BaseModel):
    name: str
    email: str

class UserResponse(BaseModel):
    id: int
    name: str
    email: str

@app.post('/users', response_model=UserResponse)
async def create_user(user: UserCreate):
    # FastAPI 自动解析请求体为 UserCreate 对象
    # FastAPI automatically parses request body as UserCreate object
    new_user = save_to_db(user)
    return new_user  # 自动序列化为 JSON

# Flask 示例 / Flask example
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/users', methods=['POST'])
def create_user():
    data = request.get_json()  # 解析请求 JSON
    if not data:
        return jsonify({'error': 'Invalid JSON'}), 400
    # 处理数据 / Process data
    return jsonify({'id': 1, 'name': data['name']}), 201

JSON 与 Python dataclass 的集成

Python 3.7+ 引入的 dataclass 是组织数据结构的简洁方式,通过 dataclasses.asdict()dataclasses.fields() 可以与 JSON 序列化集成:

对于 Python 3.10+,还可以使用 dataclasses.dataclass 配合 __post_init__ 进行验证,或者使用更新的 dataclass-wizardcattrs 等库实现更完整的 JSON 序列化支持,包括嵌套对象的自动递归序列化和类型检查。这些工具在性能和功能性上比手动转换更可靠,尤其适合复杂数据模型的项目。

from dataclasses import dataclass, asdict, field
from typing import List
import json

@dataclass
class Address:
    city: str
    country: str

@dataclass
class User:
    id: int
    name: str
    address: Address
    tags: List[str] = field(default_factory=list)

# 序列化:dataclass → dict → JSON
# Serialize: dataclass → dict → JSON
user = User(id=1, name="Alice", address=Address(city="Beijing", country="China"))
user_dict = asdict(user)  # 递归转换为字典
json_str = json.dumps(user_dict, ensure_ascii=False, indent=2)

# 反序列化:JSON → dict → dataclass(需手动处理嵌套)
# Deserialize: JSON → dict → dataclass (need to handle nesting manually)
data = json.loads(json_str)
address = Address(**data['address'])
user = User(**{**data, 'address': address})

立即免费使用相关工具

免费使用 →