Python 中的 JSON 处理教程

JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成。本教程将详细介绍如何在 Python 中处理 JSON 数据。

JSON 基础

JSON 数据结构

JSON 支持以下几种基本数据结构:

  • 对象:用花括号 {} 包裹,表示键值对集合,格式为 {"key1": "value1", "key2": "value2"}
  • 数组:用方括号 [] 包裹,表示有序值集合,格式为 ["value1", "value2", "value3"]
  • :可以是字符串、数字、布尔值、null、对象或数组

JSON 与 Python 类型对应关系

JSON 类型Python 类型
objectdict
arraylist
stringstr
numberint/float
trueTrue
falseFalse
nullNone

读取 JSON 数据

Python 的 json 模块提供了处理 JSON 数据的功能。

从字符串加载 JSON

import json

json_str = '''
{
    "name": "John",
    "age": 30,
    "city": "New York",
    "hobbies": ["reading", "traveling"],
    "married": false
}
'''

# 将JSON字符串转换为Python对象
data = json.loads(json_str)

print(type(data))  # <class 'dict'>
print(data["name"])  # John
print(data["hobbies"][0])  # reading

从文件加载 JSON

import json

# 假设有一个data.json文件
with open('data.json', 'r', encoding='utf-8') as file:
    data = json.load(file)  # 直接使用load方法从文件对象加载

print(data)

写入 JSON 数据

将 Python 对象转换为 JSON 字符串

import json

data = {
    "name": "张三",
    "age": 28,
    "city": "北京",
    "hobbies": ["摄影", "编程"],
    "married": True
}

# 将Python对象转换为JSON字符串
json_str = json.dumps(data, ensure_ascii=False, indent=4)
print(json_str)

将 Python 对象写入 JSON 文件

import json

data = {
    "name": "李四",
    "age": 35,
    "city": "上海",
    "hobbies": ["游泳", "音乐"],
    "married": False
}

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

高级用法

处理复杂对象

如果需要处理自定义对象,可以使用 default 参数指定转换函数:

import json
from datetime import datetime

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

def user_encoder(obj):
    if isinstance(obj, User):
        return {
            "name": obj.name,
            "age": obj.age,
            "created_at": obj.created_at.isoformat()
        }
    elif isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")

user = User("王五", 40)
json_str = json.dumps(user, default=user_encoder, ensure_ascii=False, indent=2)
print(json_str)

解析 JSON 时的类型转换

可以使用 object_hook 参数在解析 JSON 时进行自定义转换:

import json
from datetime import datetime

def json_decoder(dct):
    if "created_at" in dct:
        try:
            dct["created_at"] = datetime.fromisoformat(dct["created_at"])
        except ValueError:
            pass
    return dct

json_str = '''
{
    "name": "赵六",
    "age": 45,
    "created_at": "2023-01-15T10:30:00"
}
'''

data = json.loads(json_str, object_hook=json_decoder)
print(data["created_at"])  # 2023-01-15 10:30:00
print(type(data["created_at"]))  # <class 'datetime.datetime'>

性能优化

对于大型 JSON 文件,可以使用 ijson 库进行流式处理:

import ijson

# 流式处理大型JSON文件
with open('large_file.json', 'rb') as file:
    for prefix, event, value in ijson.parse(file):
        print(f"prefix: {prefix}, event: {event}, value: {value}")

最佳实践

  1. 编码问题:总是显式指定 encoding='utf-8'ensure_ascii=False 以正确处理非ASCII字符
  2. 文件操作:使用 with 语句确保文件正确关闭
  3. 错误处理:处理可能的 JSON 解析错误
  4. 性能考虑:对于大型 JSON 数据,考虑使用流式处理
  5. 安全性:不要解析来自不可信源的 JSON 数据

常见问题解决方案

处理日期时间对象

import json
from datetime import datetime

def datetime_encoder(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")

data = {
    "event": "会议",
    "time": datetime.now()
}

json_str = json.dumps(data, default=datetime_encoder, ensure_ascii=False)
print(json_str)

处理自定义类实例

import json

class Product:
    def __init__(self, id, name, price):
        self.id = id
        self.name = name
        self.price = price

def product_encoder(obj):
    if isinstance(obj, Product):
        return obj.__dict__
    raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")

product = Product(1, "笔记本电脑", 5999)
json_str = json.dumps(product, default=product_encoder, ensure_ascii=False)
print(json_str)

总结

Python 的 json 模块提供了强大的 JSON 处理能力,可以轻松实现 Python 对象与 JSON 数据之间的转换。掌握这些技术对于网络爬虫、API 开发和数据处理等场景都非常重要。在实际应用中,应根据具体需求选择合适的处理方法,并注意编码、性能和安全性等问题。