🎯 课程主题
使用 LangChain 的 JSONLoader 加载 JSON 文件,重点掌握 jq schema 表达式的编写技巧。
📝 核心知识点
1. JSONLoader 概述
JSON 格式数据在实际开发中占比很大(数据传输、配置存储等),但 JSON 结构灵活多变,因此 JSONLoader 需要借助 jq 库提供的 schema 表达式来精确指定要提取的内容。
核心参数:
| 参数 | 说明 |
|---|---|
file_path | JSON 文件路径 |
jq_schema | jq schema 表达式,指定提取规则 |
text_content | 提取的内容是否为字符串类型(默认 True) |
2. jq Schema 语法速查
| 表达式 | 含义 | 适用场景 |
|---|---|---|
. | 提取整个 JSON 根节点 | 提取全部内容 |
.[] | 提取列表(数组)中的所有元素 | JSON 数组 |
.key | 提取指定 key 对应的 value | 嵌套对象中取某个字段 |
.key[] | 提取 key 对应列表中的所有元素 | 对象内的数组 |
.key[].field | 链式导航:取列表中每个元素的 field | 深度嵌套提取 |
{...} | 构造新的 JSON 对象 | 字段重组/合并 |
3. text_content 参数详解
text_content=True(默认):要求提取的内容必须是字符串类型。如果内容为字典/列表 → 报错text_content=False:允许提取的内容为非字符串(字典、列表等),以 JSON 字符串形式存入page_content
判断规则:看你要提取的最终结果是不是字符串。是字符串 → 不设置或用 True;是对象/数组 → 必须设为 False。
🏗️ 架构与工作流
JSON 文件
│
▼
┌─────────────────────────────────┐
│ JSONLoader │
│ file_path = "xxx.json" │
│ jq_schema = ".messages[].content" │ ← jq schema 指定提取路径
│ text_content = True/False │ ← 匹配结果类型
└──────────────┬──────────────────┘
│ .load()
▼
List[Document]
├─ page_content: 提取出的内容
└─ metadata: {"source": "文件路径"}
💻 代码实战
示例一:提取全部内容
from langchain_community.document_loaders import JSONLoader
loader = JSONLoader(
file_path="../asset/load/04-chat.json",
jq_schema=".", # 提取整个 JSON
text_content=False # 整体不是字符串,必须设为 False!
)
docs = loader.load()
# docs[0].page_content → 整个 JSON 内容
示例二:提取嵌套字段(字符串类型)
# JSON 结构: {"messages": [{"role": "user", "content": "Hello"}]}
# 需求:提取 messages 列表中每个元素的 content 字段
loader = JSONLoader(
file_path="../asset/load/04-chat.json",
jq_schema=".messages[].content" # 点 messages → 取列表 → 每个元素的 content
# text_content 默认为 True,因为 content 的值是字符串
)
docs = loader.load()
# docs[0].page_content → "Hello"
示例三:提取嵌套对象(非字符串类型)
# JSON 结构: {"data": {"items": [{"id": 1, "title": "...", "content": "..."}]}}
# 需求:提取 items 列表中所有元素(对象形式)
loader = JSONLoader(
file_path="../asset/load/05-articles.json",
jq_schema=".data.items[]", # 提取 items 数组中的每个对象
text_content=False # 提取的是对象,不是字符串!
)
docs = loader.load()
# 每个 doc.page_content 是一个 JSON 对象字符串
# 包含 id、title、content 等完整字段
示例四:字段提取(字符串)
# 在示例三的基础上,只提取每个 item 的 content(字符串)
loader = JSONLoader(
file_path="../asset/load/05-articles.json",
jq_schema=".data.items[].content"
# text_content 默认 True,content 是字符串
)
docs = loader.load()
# docs[0].page_content → 第一篇文章的 content 文本
示例五:字段重组(高级用法)
# 需求:将 items 中的 title 和 content 合并为新的 content 字段,
# 同时保留 author、created_at 字段
loader = JSONLoader(
file_path="../asset/load/05-articles.json",
jq_schema=""".data.items[] | {
author: .author,
created_at: .created_at,
content: "\(.title)\n\(.content)" # title + content 合并
}""",
text_content=False # 重组后仍是对象
)
docs = loader.load()
# 每个 doc.page_content 为重组后的 JSON 字符串
# {"author": "...", "created_at": "...", "content": "标题\n正文"}
⚠️ 常见问题与避坑指南
text_content未正确设置:最常见错误。提取对象/数组时忘记设text_content=False会报错Expected string but got dict- jq schema 必须以
.开头:所有 schema 表达式都从根节点.开始 - 文件路径验证:PyCharm 中按住
Ctrl悬停路径,变为超链接表示路径正确 - schema 编写困难时:可将 JSON 结构和需求描述一起交给 AI 辅助生成 jq schema 表达式
- 管道符
|:jq 支持管道操作,用于对提取结果做进一步转换/重组
💡 个人总结与延伸
- JSONLoader 的核心难点不在加载本身,而在 jq schema 的编写——它类似正则表达式,是一种领域特定语言
text_content参数本质是类型断言:告诉 Loader 你期望提取的结果是什么类型- 实际开发中,jq schema 可与 AI 协作编写:将原始 JSON 结构 + 提取需求输入 AI,让其生成正确的 schema
- JSONLoader 仍遵循 Document Loader 统一模式:构造 →
.load()→List[Document]