Skip to content

06 json处理

做Web开发、调API、读配置文件,几乎天天都要和JSON打交道。JSON是一种轻量级的数据交换格式,长得像Python的字典和列表,但本质上是字符串。

Python的json模块就是专门处理JSON的——把Python对象转成JSON字符串(序列化),或者把JSON字符串转成Python对象(反序列化)。

一、JSON与Python类型映射

JSON和Python的数据类型有对应关系:

JSON类型Python类型
object {}dict
array []list
string ""str
numberint / float
true / falseTrue / False
nullNone

二、序列化:Python → JSON

2.1 json.dumps()

把Python对象转成JSON字符串。

python
import json

# 字典转JSON
data = {"name": "大志", "age": 28, "active": True}
json_str = json.dumps(data)
print(json_str)
# {"name": "\u5927\u5fd7", "age": 28, "active": true}

默认情况下,中文会被转义成Unicode。要保留中文,设置ensure_ascii=False

python
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
# {"name": "大志", "age": 28, "active": true}

2.2 格式化输出

python
import json

data = {"name": "大志", "skills": ["Python", "LangChain"], "age": 28}

# 美化输出(缩进)
print(json.dumps(data, ensure_ascii=False, indent=2))

输出:

json
{
  "name": "大志",
  "skills": [
    "Python",
    "LangChain"
  ],
  "age": 28
}

2.3 关键参数

python
import json

data = {"name": "大志", "age": 28, "skills": ["Python", "LangChain"]}

# indent:缩进级别
json.dumps(data, indent=2)

# separators:分隔符(默认(', ', ': '))
json.dumps(data, separators=(',', ':'))  # 紧凑输出

# sort_keys:按键排序
json.dumps(data, sort_keys=True, ensure_ascii=False)

# ensure_ascii:是否转义非ASCII字符
json.dumps(data, ensure_ascii=False)  # 保留中文

2.4 json.dump()

把Python对象直接写入文件。

python
import json

data = {"name": "大志", "age": 28}

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

三、反序列化:JSON → Python

3.1 json.loads()

把JSON字符串转成Python对象。

python
import json

json_str = '{"name": "大志", "age": 28, "active": true}'
data = json.loads(json_str)

print(data)
# {'name': '大志', 'age': 28, 'active': True}

print(type(data))  # <class 'dict'>
print(data["name"])  # 大志

3.2 json.load()

从文件读取JSON。

python
import json

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

print(data)

3.3 解析嵌套JSON

python
import json

json_str = '''
{
    "agent": {
        "name": "大志助手",
        "model": "gpt-5",
        "tools": ["search", "calculator", "code"]
    },
    "version": 1.0
}
'''

config = json.loads(json_str)

# 访问嵌套数据
config["agent"]["name"]       # '大志助手'
config["agent"]["tools"][0]   # 'search'

3.4 解析JSON数组

python
import json

json_str = '[{"name": "大志", "age": 28}, {"name": "小明", "age": 25}]'
users = json.loads(json_str)

for user in users:
    print(f"{user['name']}: {user['age']}岁")

四、处理特殊类型

json模块默认只能处理基本类型(dict、list、str、int、float、bool、None)。遇到其他类型会报错:

python
import json
from datetime import datetime

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

4.1 自定义序列化

default参数指定一个转换函数:

python
import json
from datetime import datetime

def default_serializer(obj):
    """自定义序列化函数"""
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Object of type {type(obj)} is not JSON serializable")

data = {"time": datetime.now(), "name": "大志"}
json_str = json.dumps(data, default=default_serializer, ensure_ascii=False)
print(json_str)
# {"time": "2026-06-13T10:30:00.123456", "name": "大志"}

4.2 处理Decimal

python
import json
from decimal import Decimal

data = {"price": Decimal("99.99")}

# 方法1:转成字符串
json.dumps(data, default=str)

# 方法2:转成float
json.dumps(data, default=lambda x: float(x) if isinstance(x, Decimal) else None)

4.3 自定义反序列化

object_hook参数把JSON对象转成自定义类型:

python
import json

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

def user_hook(dct):
    """把JSON对象转成User对象"""
    if "name" in dct and "age" in dct:
        return User(dct["name"], dct["age"])
    return dct

json_str = '{"name": "大志", "age": 28}'
user = json.loads(json_str, object_hook=user_hook)

print(type(user))  # <class 'User'>
print(user.name)   # 大志

五、处理JSON Lines

JSON Lines是一种常见的日志格式,每行一个JSON对象:

json
{"name": "大志", "age": 28}
{"name": "小明", "age": 25}
{"name": "小红", "age": 23}

解析JSON Lines:

python
import json

def parse_jsonl(text):
    """解析JSON Lines格式"""
    result = []
    for line in text.strip().split("\n"):
        if line.strip():
            result.append(json.loads(line))
    return result

# 从文件读取JSON Lines
with open("data.jsonl", "r", encoding="utf-8") as f:
    for line in f:
        data = json.loads(line.strip())
        print(data)

六、命令行工具

Python提供了命令行工具来格式化和验证JSON:

bash
# 格式化JSON文件
python -m json.tool data.json

# 格式化并输出到文件
python -m json.tool data.json > formatted.json

# 验证JSON是否合法
echo '{"name": "test"}' | python -m json.tool

# 管道输入
curl -s https://api.example.com/data | python -m json.tool

七、实用技巧

7.1 安全地解析JSON

python
import json

def safe_json_loads(s, default=None):
    """安全地解析JSON,失败时返回默认值"""
    try:
        return json.loads(s)
    except json.JSONDecodeError:
        return default

data = safe_json_loads("invalid json", {})

7.2 合并多个JSON文件

python
import json
from pathlib import Path

def merge_json_files(directory):
    """合并目录下所有JSON文件"""
    result = {}
    for p in Path(directory).glob("*.json"):
        with open(p, "r", encoding="utf-8") as f:
            data = json.load(f)
            if isinstance(data, dict):
                result.update(data)
    return result

7.3 JSON美化打印

python
import json

def pretty_json(data):
    """美化打印JSON"""
    return json.dumps(data, ensure_ascii=False, indent=2, sort_keys=True)

# 调试时使用
print(pretty_json(api_response))

7.4 深度合并JSON

python
import json

def deep_merge(base, override):
    """深度合并两个字典"""
    result = base.copy()
    for key, value in override.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = deep_merge(result[key], value)
        else:
            result[key] = value
    return result

# 合并配置文件
with open("config.default.json") as f:
    default_config = json.load(f)
with open("config.json") as f:
    user_config = json.load(f)

config = deep_merge(default_config, user_config)

7.5 处理大文件

处理大JSON文件时,可以使用ijson库进行流式解析:

python
# pip install ijson
import ijson

# 流式解析大JSON文件
with open("large.json", "rb") as f:
    for item in ijson.items(f, "data.item"):
        print(item)

八、总结

json模块的核心就四个函数:

函数作用
json.dumps(obj)Python对象 → JSON字符串
json.loads(s)JSON字符串 → Python对象
json.dump(obj, f)Python对象 → 写入文件
json.load(f)从文件读取 → Python对象

常用参数:

参数作用
ensure_ascii=False保留中文,不转义
indent=2美化输出,缩进2格
sort_keys=True按键名排序
default=func自定义序列化函数
object_hook=func自定义反序列化函数

记住dumps()loads()就够了,带s的是操作字符串,不带s的是操作文件。