← 返回博客

Python 和 JSON:完整教程及示例

使用 json 模块掌握 Python 中的 JSON。学习解析、生成和操作 JSON 数据的实用示例和最佳实践。

Big JSON Team13 分钟阅读programming
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

13 分钟阅读

# Python 和 JSON:完整教程及示例

Python 的内置 json 模块使处理 JSON 数据变得简单高效。本综合指南涵盖了从基本解析到高级技术的所有内容,并提供了实际示例。

Python json 模块简介

json 模块是 Python 标准库的一部分,无需安装:
import json

主要功能

  • json.loads():解析 JSON 字符串
  • json.load():从文件读取 JSON
  • json.dumps():将对象转换为 JSON 字符串
  • json.dump():将对象写入 JSON 文件

解析 JSON

json.loads() - 解析 JSON 字符串

将 JSON 字符串转换为 Python 对象:

import json

json_string = '{"name": "张三", "age": 30, "city": "北京"}'

data = json.loads(json_string)

print(data['name']) # "张三"

print(type(data)) # <class 'dict'>

json.load() - 从文件读取

从文件加载 JSON 数据:

import json

with open('data.json', 'r', encoding='utf-8') as file:

data = json.load(file)

print(data)

data.json:
{

"users": [

{"name": "张三", "age": 30},

{"name": "李四", "age": 25}

]

}

输出:
{'users': [{'name': '张三', 'age': 30}, {'name': '李四', 'age': 25}]}

处理解析错误

import json

json_string = '{"name": "张三", "age": 30,}' # 尾随逗号

try:

data = json.loads(json_string)

except json.JSONDecodeError as e:

print(f"错误:{e}")

print(f"行 {e.lineno},列 {e.colno}")

生成 JSON

json.dumps() - 转换为 JSON 字符串

将 Python 对象转换为 JSON 字符串:

import json

data = {

"name": "王五",

"age": 28,

"active": True,

"skills": ["Python", "JavaScript"],

"address": None

}

json_string = json.dumps(data, ensure_ascii=False)

print(json_string)

# {"name": "王五", "age": 28, "active": true, "skills": ["Python", "JavaScript"], "address": null}

美化输出

使用缩进使 JSON 可读:

json_string = json.dumps(data, indent=2, ensure_ascii=False)

print(json_string)

输出:
{

"name": "王五",

"age": 28,

"active": true,

"skills": [

"Python",

"JavaScript"

],

"address": null

}

json.dump() - 写入文件

将 Python 对象保存到 JSON 文件:

import json

data = {

"company": "科技创新",

"employees": [

{"name": "张三", "role": "开发者"},

{"name": "李四", "role": "设计师"}

]

}

with open('output.json', 'w', encoding='utf-8') as file:

json.dump(data, file, indent=2, ensure_ascii=False)

数据类型映射

Python 到 JSON

| Python 类型 | JSON 类型 |

|------------|----------|

| dict | object |

| list, tuple | array |

| str | string |

| int, float | number |

| True | true |

| False | false |

| None | null |

示例:
import json

python_data = {

"字典": {"key": "value"},

"列表": [1, 2, 3],

"元组": (4, 5, 6),

"字符串": "文本",

"整数": 42,

"浮点数": 3.14,

"布尔值": True,

"空值": None

}

json_string = json.dumps(python_data, ensure_ascii=False)

print(json_string)

JSON 到 Python

| JSON 类型 | Python 类型 |

|----------|-----------|

| object | dict |

| array | list |

| string | str |

| number (int) | int |

| number (real) | float |

| true | True |

| false | False |

| null | None |

常用选项

ensure_ascii

控制非 ASCII 字符的处理:

data = {"name": "张三", "city": "北京"}

# 默认(转义非 ASCII)

print(json.dumps(data))

# {"name": "\u5f20\u4e09", "city": "\u5317\u4eac"}

# ensure_ascii=False(保留 Unicode)

print(json.dumps(data, ensure_ascii=False))

# {"name": "张三", "city": "北京"}

sort_keys

按字母顺序排序键:

data = {"z": 1, "a": 2, "m": 3}

print(json.dumps(data, sort_keys=True))

# {"a": 2, "m": 3, "z": 1}

separators

自定义分隔符以压缩输出:

data = {"name": "张三", "age": 30}

# 默认

print(json.dumps(data))

# {"name": "张三", "age": 30}

# 压缩

print(json.dumps(data, separators=(',', ':')))

# {"name":"张三","age":30}

indent

控制缩进级别:

data = {"name": "张三", "skills": ["Python", "Java"]}

# 2 空格缩进

print(json.dumps(data, indent=2, ensure_ascii=False))

# 4 空格缩进

print(json.dumps(data, indent=4, ensure_ascii=False))

# 制表符缩进

print(json.dumps(data, indent='\t', ensure_ascii=False))

处理复杂数据

嵌套结构

import json

data = {

"company": "科技创新",

"departments": [

{

"name": "工程",

"employees": [

{"name": "张三", "role": "开发者"},

{"name": "李四", "role": "测试"}

]

},

{

"name": "设计",

"employees": [

{"name": "王五", "role": "UI 设计师"}

]

}

]

}

# 访问嵌套数据

print(data['departments'][0]['employees'][0]['name']) # "张三"

# 转换为 JSON

json_string = json.dumps(data, indent=2, ensure_ascii=False)

print(json_string)

自定义对象

默认参数

import json

from datetime import datetime, date

class Employee:

def __init__(self, name, hire_date):

self.name = name

self.hire_date = hire_date

def json_serializer(obj):

"""自定义 JSON 序列化器"""

if isinstance(obj, (datetime, date)):

return obj.isoformat()

if isinstance(obj, Employee):

return {

"name": obj.name,

"hire_date": obj.hire_date

}

raise TypeError(f"类型 {type(obj)} 不可 JSON 序列化")

emp = Employee("张三", date(2020, 1, 15))

json_string = json.dumps(emp, default=json_serializer, ensure_ascii=False)

print(json_string)

# {"name": "张三", "hire_date": "2020-01-15"}

JSONEncoder 子类

import json

from datetime import datetime

class CustomEncoder(json.JSONEncoder):

def default(self, obj):

if isinstance(obj, datetime):

return obj.isoformat()

if isinstance(obj, set):

return list(obj)

return super().default(obj)

data = {

"timestamp": datetime.now(),

"tags": {"python", "json", "教程"}

}

json_string = json.dumps(data, cls=CustomEncoder, ensure_ascii=False)

print(json_string)

处理日期时间

import json

from datetime import datetime

# 序列化

now = datetime.now()

data = {

"event": "会议",

"time": now.isoformat()

}

json_string = json.dumps(data, ensure_ascii=False)

print(json_string)

# 反序列化

loaded = json.loads(json_string)

meeting_time = datetime.fromisoformat(loaded['time'])

print(meeting_time)

实际示例

示例 1:处理 API 响应

import json

import requests

# 获取数据

response = requests.get('https://api.example.com/users')

data = response.json() # 或 json.loads(response.text)

# 处理数据

for user in data['users']:

print(f"姓名:{user['name']},年龄:{user['age']}")

# 保存到文件

with open('users.json', 'w', encoding='utf-8') as f:

json.dump(data, f, indent=2, ensure_ascii=False)

示例 2:配置文件

import json

# 读取配置

def load_config(filename):

with open(filename, 'r', encoding='utf-8') as f:

return json.load(f)

# 保存配置

def save_config(filename, config):

with open(filename, 'w', encoding='utf-8') as f:

json.dump(config, f, indent=2, ensure_ascii=False)

# 使用

config = load_config('config.json')

config['database']['port'] = 5432

save_config('config.json', config)

config.json:
{

"database": {

"host": "localhost",

"port": 5432,

"name": "mydb"

},

"logging": {

"level": "INFO"

}

}

示例 3:数据转换

import json

# CSV 到 JSON

def csv_to_json(csv_file, json_file):

import csv

data = []

with open(csv_file, 'r', encoding='utf-8') as f:

reader = csv.DictReader(f)

for row in reader:

data.append(row)

with open(json_file, 'w', encoding='utf-8') as f:

json.dump(data, f, indent=2, ensure_ascii=False)

# 使用

csv_to_json('data.csv', 'data.json')

示例 4:验证 JSON

import json

def validate_json(json_string):

"""验证 JSON 字符串"""

try:

json.loads(json_string)

return True, "有效的 JSON"

except json.JSONDecodeError as e:

return False, f"无效的 JSON:{e}"

# 测试

test_cases = [

'{"name": "张三"}', # 有效

'{"name": "张三",}', # 无效(尾随逗号)

"{'name': 'Zhang San'}", # 无效(单引号)

]

for test in test_cases:

valid, message = validate_json(test)

print(f"{test[:20]}... → {message}")

示例 5:合并 JSON 文件

import json

from pathlib import Path

def merge_json_files(output_file, input_files):

"""合并多个 JSON 文件"""

merged = {}

for file in input_files:

with open(file, 'r', encoding='utf-8') as f:

data = json.load(f)

merged.update(data)

with open(output_file, 'w', encoding='utf-8') as f:

json.dump(merged, f, indent=2, ensure_ascii=False)

# 使用

merge_json_files('merged.json', 'file1.json', 'file2.json', 'file3.json')

性能优化

大文件处理

对于大型 JSON 文件,考虑流式处理:

import json

def process_large_json(filename):

"""逐块处理大型 JSON"""

with open(filename, 'r', encoding='utf-8') as f:

# 对于非常大的文件,考虑使用 ijson

data = json.load(f)

# 逐项处理

for item in data['items']:

process_item(item)

def process_item(item):

# 处理单个项目

pass

使用 ujson

对于更快的性能,使用 ujson

pip install ujson
import ujson

# 更快的解析

data = ujson.loads(json_string)

# 更快的序列化

json_string = ujson.dumps(data)

常见错误和解决方案

1. JSONDecodeError

问题:
json.JSONDecodeError: Expecting property name enclosed in double quotes
解决方案:
# 错误:单引号

bad = "{'name': 'Zhang San'}"

# 正确:双引号

good = '{"name": "Zhang San"}'

2. Object is not JSON serializable

问题:
TypeError: Object of type datetime is not JSON serializable
解决方案:
from datetime import datetime

import json

data = {"time": datetime.now()}

# 使用自定义序列化器

json.dumps(data, default=str)

# 或

json.dumps(data, default=lambda x: x.isoformat() if isinstance(x, datetime) else None)

3. 编码错误

问题:
UnicodeEncodeError: 'ascii' codec can't encode characters
解决方案:
# 使用 ensure_ascii=False

json.dumps(data, ensure_ascii=False)

# 或指定编码

with open('file.json', 'w', encoding='utf-8') as f:

json.dump(data, f, ensure_ascii=False)

最佳实践

1. 始终指定编码

# 推荐

with open('file.json', 'r', encoding='utf-8') as f:

data = json.load(f)

2. 使用上下文管理器

# 推荐

with open('file.json', 'w', encoding='utf-8') as f:

json.dump(data, f)

# 不推荐

f = open('file.json', 'w')

json.dump(data, f)

f.close() # 容易忘记

3. 处理异常

import json

try:

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

data = json.load(f)

except FileNotFoundError:

print("文件未找到")

except json.JSONDecodeError as e:

print(f"无效的 JSON:{e}")

except Exception as e:

print(f"错误:{e}")

4. 验证数据

import json

data = json.loads(json_string)

# 验证必需的字段

assert 'name' in data, "缺少 'name' 字段"

assert isinstance(data['age'], int), "'age' 必须是整数"

5. 使用 ensure_ascii=False 处理中文

data = {"name": "张三", "city": "北京"}

# 推荐

json.dumps(data, ensure_ascii=False)

# {"name": "张三", "city": "北京"}

# 不推荐

json.dumps(data)

# {"name": "\u5f20\u4e09", "city": "\u5317\u4eac"}

高级技术

JSON Schema 验证

from jsonschema import validate, ValidationError

import json

schema = {

"type": "object",

"properties": {

"name": {"type": "string"},

"age": {"type": "number", "minimum": 0}

},

"required": ["name"]

}

data = {"name": "张三", "age": 30}

try:

validate(instance=data, schema=schema)

print("数据有效")

except ValidationError as e:

print(f"验证失败:{e}")

JSONPath 查询

from jsonpath_ng import parse

import json

data = {

"users": [

{"name": "张三", "age": 30},

{"name": "李四", "age": 25}

]

}

# 查找所有姓名

expr = parse('$.users[].name')

names = [match.value for match in expr.find(data)]

print(names) # ['张三', '李四']

结论

Python 的 json 模块为处理 JSON 数据提供了强大而简单的工具。通过掌握其功能和最佳实践,您可以有效地:

  • ✅ 解析和生成 JSON 数据
  • ✅ 处理复杂的嵌套结构
  • ✅ 自定义序列化行为
  • ✅ 优化大文件性能
  • ✅ 处理错误和验证数据

关键要点

  • 对字符串使用 loads/dumps,对文件使用 load/dump
  • 始终使用 ensure_ascii=False 处理 Unicode
  • 使用 indent 进行可读输出
  • 使用 try/except 处理错误
  • 为自定义类型实现自定义序列化器
  • 通过这些技术,您已准备好在 Python 应用程序中自信地处理 JSON!

    Share:

    相关文章

    Read in English