JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,在Python中通过json
模块提供了完整的支持。下面我将详细讲解JSON在Python中的使用方法,包括四种核心函数:json.loads()
、json.dumps()
、json.load()
和json.dump()
。
一、JSON基础概念
1. 什么是JSON?
JSON是一种基于文本的数据格式,具有以下特点:
-
易于人阅读和编写
-
易于机器解析和生成
-
完全独立于编程语言
-
支持嵌套数据结构
2. JSON与Python数据类型对应关系
JSON类型 | Python类型 |
---|---|
object | dict |
array | list |
string | str |
number | int/float |
true/false | True/False |
null | None |
二、JSON核心函数详解
1. json.loads() - 从JSON字符串到Python对象
功能:将JSON格式的字符串解码为Python对象
语法:
json.loads(s, *, cls=None, object_hook=None, parse_float=None,
parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
示例:
import json
json_str = '{"name": "Alice", "age": 25, "is_student": false, "courses": ["Math", "Science"]}'
python_dict = json.loads(json_str)
print(python_dict)
# 输出: {'name': 'Alice', 'age': 25, 'is_student': False, 'courses': ['Math', 'Science']}
print(type(python_dict)) # <class 'dict'>
参数说明:
-
object_hook
: 可选函数,用于自定义解码后的字典对象 -
parse_float
: 指定浮点数解码函数 -
parse_int
: 指定整数解码函数
2. json.dumps() - 从Python对象到JSON字符串
功能:将Python对象编码为JSON格式的字符串
语法:
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw)
示例:
import json
python_dict = {
'name': 'Bob',
'age': 30,
'is_employed': True,
'skills': None,
'languages': ['Python', 'JavaScript']
}
json_str = json.dumps(python_dict, indent=4)
print(json_str)
# 输出:
# {
# "name": "Bob",
# "age": 30,
# "is_employed": true,
# "skills": null,
# "languages": [
# "Python",
# "JavaScript"
# ]
# }
常用参数:
-
indent
: 缩进空格数,美化输出 -
ensure_ascii
: 是否转义非ASCII字符(设为False可保留中文等) -
sort_keys
: 是否按键排序
3. json.load() - 从文件读取JSON数据
功能:从文件对象中读取JSON数据并解码为Python对象
语法:
json.load(fp, *, cls=None, object_hook=None, parse_float=None,
parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
示例:
import json
# 假设有一个data.json文件,内容为:
# {"name": "Charlie", "score": 88.5, "passed": true}
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print(data) # {'name': 'Charlie', 'score': 88.5, 'passed': True}
注意事项:
-
文件需要以读模式打开
-
文件必须包含有效的JSON内容
-
会自动关闭文件(使用with语句时)
4. json.dump() - 将JSON数据写入文件
功能:将Python对象编码为JSON格式并写入文件
语法:
json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None,
default=None, sort_keys=False, **kw)
示例:
import json
data = {
'product': 'Laptop',
'price': 999.99,
'in_stock': True,
'specs': {'RAM': '16GB', 'Storage': '512GB SSD'}
}
with open('product.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
生成的文件内容:
{
"product": "Laptop",
"price": 999.99,
"in_stock": true,
"specs": {
"RAM": "16GB",
"Storage": "512GB SSD"
}
}
三、函数对比总结
函数 | 输入源 | 输出目标 | 典型应用场景 |
---|---|---|---|
json.loads() | JSON字符串 | Python对象 | 处理API返回的JSON字符串 |
json.dumps() | Python对象 | JSON字符串 | 准备发送给API的数据 |
json.load() | 文件对象 | Python对象 | 读取本地存储的JSON配置文件 |
json.dump() | Python对象 | 文件对象 | 将数据保存为JSON文件 |
四、高级用法与技巧
1. 处理自定义对象
默认情况下,JSON模块无法序列化自定义类的实例。可以通过以下方式解决:
方法1:使用default参数指定转换函数
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def user_to_dict(user):
return {'name': user.name, 'age': user.age}
user = User('Alice', 25)
json_str = json.dumps(user, default=user_to_dict)
方法2:为类添加__dict__
方法
json_str = json.dumps(user.__dict__)
方法3:继承JSONEncoder
class UserEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, User):
return {'name': obj.name, 'age': obj.age}
return super().default(obj)
json_str = json.dumps(user, cls=UserEncoder)
2. 处理日期时间对象
JSON没有原生的日期时间类型,通常转换为字符串:
from datetime import datetime
def datetime_handler(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError("Type not serializable")
data = {'time': datetime.now()}
json_str = json.dumps(data, default=datetime_handler)
3. 处理特殊浮点值
JSON规范不支持NaN
、Infinity
等特殊浮点值,可以通过参数控制:
data = {'value': float('nan')}
# json.dumps(data) # 会报错
json.dumps(data, allow_nan=True) # 在JavaScript中可解析,但不符合严格JSON规范
五、实际应用示例
1. 配置文件读写
import json
import os
# 写入配置
config = {
'language': 'Python',
'version': '3.9',
'settings': {'theme': 'dark', 'font_size': 14}
}
config_path = 'config.json'
with open(config_path, 'w') as f:
json.dump(config, f, indent=4)
# 读取配置
if os.path.exists(config_path):
with open(config_path) as f:
loaded_config = json.load(f)
print(loaded_config)
2. API数据处理
import json
import requests
# 获取API数据
response = requests.get('https://api.example.com/data')
data = json.loads(response.text)
# 处理数据
filtered_data = [item for item in data if item['value'] > 10]
# 发送处理后的数据
headers = {'Content-Type': 'application/json'}
requests.post('https://api.example.com/processed',
data=json.dumps(filtered_data),
headers=headers)
3. 数据持久化
import json
# 保存用户数据
def save_users(users, filename):
with open(filename, 'w') as f:
json.dump([u.__dict__ for u in users], f)
# 加载用户数据
def load_users(filename):
with open(filename) as f:
return [User(**data) for data in json.load(f)]
六、常见问题与解决方案
Q1:JSONDecodeError: Expecting value: line 1 column 1 (char 0)
原因:尝试解析空字符串或无效JSON
解决:检查数据源是否包含有效JSON内容
Q2:TypeError: Object of type 'datetime' is not JSON serializable
原因:尝试序列化不支持的类型
解决:使用default参数提供自定义序列化方法
Q3:中文字符被转义为Unicode码
解决:设置ensure_ascii=False
json.dumps(data, ensure_ascii=False)
Q4:如何提高大JSON文件的处理性能?
建议:
-
使用
ijson
库处理流式大文件 -
避免一次性加载超大文件到内存
-
考虑使用更高效的数据格式如MessagePack
七、总结
JSON作为数据交换的标准格式,在Python中通过json
模块提供了简单易用的接口:
-
序列化(Python→JSON):
-
json.dumps()
生成字符串 -
json.dump()
写入文件
-
-
反序列化(JSON→Python):
-
json.loads()
从字符串解析 -
json.load()
从文件读取
-
-
关键点:
-
注意数据类型转换规则
-
处理自定义对象需要额外步骤
-
使用indent参数美化输出
-
处理非ASCII字符设置ensure_ascii=False
-
掌握这些JSON处理技巧,能够高效地在Python程序中进行数据序列化和持久化操作,为Web开发、数据分析和系统集成等场景提供坚实基础。