在开发 RAG(检索增强生成)和
Agent(智能体)系统时,我们经常需要让大模型输出结构化数据 (如商品列表、用户信息、配置参数等),以便程序能够直接解析和使用。 而
JSON (JavaScript Object Notation) 正是实现这一目标的核心技术。它轻量、易读,且能被几乎所有编程语言支持。本文将深入讲解 JSON 的基础概念、与 Python数据结构的对应关系,以及如何使用 Python 标准库
json进行高效的数据转换。
什么是 JSON?
JSON 是一种带有格式的字符串,用于存储和传输数据。它的核心优势在于:
- ✅ 结构清晰:通过键值对和数组清晰地表达数据层级。
- ✅ 语言无关:任何语言都能解析和生成 JSON。
- ✅ 易于人机阅读:格式简洁,既方便程序处理,也方便开发者调试。
💡 重要认知 :JSON 本质上是字符串。它只是长得像 Python 字典或列表,但在被解析之前,它就是一段文本。
JSON 与 Python 数据结构的映射
理解 JSON 类型与 Python 类型的对应关系是操作 JSON 的关键。
| JSON 类型 | Python 类型 | 说明 |
|---|---|---|
Object {} |
dict 字典 |
键值对集合,键必须是字符串 |
Array [] |
list 列表 |
有序的元素集合 |
String "" |
str 字符串 |
文本数据 |
Number 123 |
int/float 整数/浮点数 |
数值数据 |
Boolean true/false |
bool 布尔值 |
True / False |
Null null |
None 空值 |
表示空或无 |
示例 1:JSON 对象 ➡️ Python 字典
json
{
"age": 11,
"name": "周杰伦",
"hobby": ["唱", "跳", "rap"],
"other": {
"身高": 172,
"体重": 68
}
}
⬇️ 对应 Python 字典 ⬇️
python
{
"age": 11,
"name": "周杰伦",
"hobby": ["唱", "跳", "rap"],
"other": {
"身高": 172,
"体重": 68
}
}
示例 2:JSON 数组 ➡️ Python 列表
json
[
{"name": "周杰伦", "age": 11},
{"name": "蔡依林", "age": 12},
{"name": "小明", "age": 16}
]
⬇️ 对应 Python 列表(内含多个字典)⬇️
python
[
{"name": "周杰伦", "age": 11},
{"name": "蔡依林", "age": 12},
{"name": "小明", "age": 16}
]
🛠️ Python 中的 JSON 操作:json 模块
Python 内置了 json 模块,无需安装即可使用。它提供了两个最核心的函数:dumps 和 loads。
1. json.dumps(): Python ➡️ JSON 字符串
作用 :将 Python 对象(字典、列表等)序列化为 JSON 格式的字符串。
python
import json
data = {
"name": "周杰伦",
"age": 11,
"hobby": ["唱", "跳", "rap"]
}
# 转换为 JSON 字符串
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
# 输出: {"name": "周杰伦", "age": 11, "hobby": ["唱", "跳", "rap"]}
print(type(json_str))
# 输出: <class 'str'> <-- 注意,它现在是字符串类型!
🔑 关键参数:ensure_ascii=False
- 默认行为 :
ensure_ascii=True会将所有非 ASCII 字符(如中文)转义为\uXXXX形式。 - 推荐设置 :
ensure_ascii=False可以直接保留中文,使输出的 JSON 字符串更易读。
2. json.loads(): JSON 字符串 ➡️ Python
作用 :将 JSON 格式的字符串反序列化为 Python 对象。
python
import json
json_str = '{"name": "周杰伦", "age": 11, "hobby": ["唱", "跳", "rap"]}'
# 转换为 Python 对象
data = json.loads(json_str)
print(data)
# 输出: {'name': '周杰伦', 'age': 11, 'hobby': ['唱', '跳', 'rap']}
print(type(data))
# 输出: <class 'dict'> <-- 现在它是真正的字典了!
# 现在可以像操作普通字典一样操作它
print(data["name"]) # 输出: 周杰伦
🚀 实战场景:在大模型应用中处理 JSON
在 RAG 和 Agent 开发中,JSON 的典型工作流如下:
场景 1:让大模型输出结构化数据
我们希望通过 Prompt 让模型返回一个标准的 JSON 对象,而不是自由文本。
python
from openai import OpenAI
import json
client = OpenAI(...)
prompt = """
请提取以下文本中的产品名称和价格,并以 JSON 格式返回:
"最新款 iPhone 15 Pro 售价为 7999 元,性能强劲。"
要求格式:
{"product_name": "产品名", "price": 价格数字}
"""
response = client.chat.completions.create(
model="qwen-plus",
messages=[{"role": "user", "content": prompt}]
)
model_output = response.choices[0].message.content.strip()
print(f"模型原始输出: {model_output}")
# 【关键步骤】解析模型返回的 JSON 字符串
try:
# 有时模型会包裹在 ```json ... ```中,需要先清理
if model_output.startswith("```json"):
model_output = model_output[7:-3]
elif model_output.startswith("```"):
model_output = model_output[3:-3]
data = json.loads(model_output)
print(f"✅ 解析成功!")
print(f"产品: {data['product_name']}, 价格: {data['price']}")
except json.JSONDecodeError as e:
print(f"❌ JSON 解析失败: {e}")
print("模型可能没有严格按照 JSON 格式输出")
场景 2:将程序数据发送给大模型
有时我们需要将复杂的 Python 数据结构(如配置、历史状态)作为上下文传给模型。
python
import json
# 假设这是你的 Agent 当前状态
agent_state = {
"current_step": "search_database",
"parameters": {
"query": "2023年财报",
"limit": 5
},
"history": ["init", "parse_user_input"]
}
# 将其转为 JSON 字符串嵌入到 Prompt 中
context_json = json.dumps(agent_state, ensure_ascii=False)
prompt = f"""
你是一个智能助手。当前的系统状态如下:
{context_json}
请根据状态决定下一步操作。
"""
# 发送 prompt 给模型...
⚠️ 常见陷阱与注意事项
1. 单引号 vs 双引号
- JSON 标准 :严格要求使用双引号
"包裹键和字符串值。 - Python 习惯 :常用单引号
'。 - 错误示例 :
{'name': '周杰伦'}这不是合法的 JSON,json.loads()会报错。 - 正确示例 :
{"name": "周杰伦"}
2. 尾部逗号
- JSON 标准:不允许在最后一个元素后加逗号。
- 错误示例 :
{"a": 1,} - 正确示例 :
{"a": 1}
3. 注释不支持
- JSON 标准 :原生不支持注释
//或/* */。 - 如果需要在配置文件中写注释,考虑使用 YAML 或 TOML,或者在解析前用正则移除注释。
4. 数据类型限制
- JSON 只支持基本数据类型。Python 的
datetime,set,tuple等无法直接序列化。 - 解决方案:自定义序列化逻辑,或在序列化前手动转换为字符串/列表。
🚀 总结
JSON 是连接大模型与传统程序的桥梁。掌握它意味着:
✅ 能让模型输出程序可直接使用的结构化数据
✅ 能将复杂状态无损地传递给模型
✅ 能轻松实现不同系统间的数据交互
核心口诀:
- Python ➡️ JSON :
json.dumps(obj, ensure_ascii=False) - JSON ➡️ Python :
json.loads(json_string) - 记住 :JSON 是字符串,使用前必须
loads解析!