【langchain学习】从零开始掌握 JSONLoader:轻松解析复杂 JSON 数据
在使用 JSONLoader
之前,我们需要确保安装了 jq
库:
pip install -U jq
如果不能安装的话,可以用:(如果你是win系统,则不能直接使用jq)
conda install jq
接下来,我们通过一个关于 Jonas Vingegaard 的 JSON 数据示例来演示 JSONLoader
的基本功能。
JSON 示例数据
{"tour_de_france": {"year": 2023,"winner": "Jonas Vingegaard","team": "Team Jumbo-Visma","stages": [{"stage": 1,"date": "2023-07-01","distance_km": 182,"result": {"position": 2,"time": "4h 12m 34s"}},{"stage": 2,"date": "2023-07-02","distance_km": 209,"result": {"position": 1,"time": "5h 01m 45s"}},{"stage": 3","date": "2023-07-03","distance_km": 176,"result": {"position": 3,"time": "3h 58m 21s"}}],"total_time": "13h 12m 40s","average_speed_kmh": 41.3}
}
1.1 提取所有赛段结果
我们首先通过 JSONLoader
提取 Jonas Vingegaard 在所有赛段中的比赛结果:
from langchain_community.document_loaders import JSONLoaderfile_path = './vingegaard_tdf_2023.json'
loader = JSONLoader(file_path=file_path,jq_schema='.tour_de_france.stages[].result',text_content=False
)docs = loader.load()
for doc in docs:print(doc.page_content)
输出:
{"position": 2, "time": "4h 12m 34s"}
{"position": 1, "time": "5h 01m 45s"}
{"position": 3, "time": "3h 58m 21s"}
在这个例子中,我们使用 jq_schema
提取了 tour_de_france.stages[].result
,即每个赛段的结果信息。
1.2 提取比赛的总时间和平均速度
如果我们只关心比赛的总时间和平均速度,可以通过以下 jq_schema
进行提取:
loader = JSONLoader(file_path=file_path,jq_schema='.tour_de_france | {total_time, average_speed_kmh}',text_content=False
)docs = loader.load()
print(docs[0].page_content)
输出:
{"total_time": "13h 12m 40s","average_speed_kmh": 41.3
}
这里我们提取了 total_time
和 average_speed_kmh
,这些数据可以帮助我们快速了解 Jonas Vingegaard 在整个比赛中的表现。
1.3 提取特定赛段的信息
假设我们想要提取第 2 赛段的详细信息:
loader = JSONLoader(file_path=file_path,jq_schema='.tour_de_france.stages[] | select(.stage == 2)',text_content=False
)docs = loader.load()
print(docs[0].page_content)
输出:
{"stage": 2,"date": "2023-07-02","distance_km": 209,"result": {"position": 1,"time": "5h 01m 45s"}
}
通过这个查询,我们精确地定位到了第 2 赛段的详细信息,包括日期、距离和比赛结果。
2. 深入探讨:自定义元数据处理
JSONLoader
不仅可以提取数据,还允许我们自定义元数据。这对于需要对数据进行进一步处理和分析的场景非常有用。
2.1 自定义元数据示例
我们可以定义一个 metadata_func
来生成自定义元数据,比如增加一个“赛段总数”作为元数据:
def custom_metadata(json_obj, metadata):metadata['total_stages'] = len(json_obj['tour_de_france']['stages'])return metadataloader = JSONLoader(file_path=file_path,jq_schema='.tour_de_france.stages[].result',metadata_func=custom_metadata,text_content=False
)docs = loader.load()
for doc in docs:print(doc.metadata)
输出:
{'source': './vingegaard_tdf_2023.json', 'seq_num': 1, 'total_stages': 3}
{'source': './vingegaard_tdf_2023.json', 'seq_num': 2, 'total_stages': 3}
{'source': './vingegaard_tdf_2023.json', 'seq_num': 3, 'total_stages': 3}
通过这个例子,我们可以看到如何利用 metadata_func
为每个文档对象添加自定义的元数据,这在大型数据集处理时非常有帮助。
3. 扩展功能:异步和惰性加载
在处理大规模 JSON 文件时,JSONLoader
提供了异步加载和惰性加载的选项,以优化内存使用和处理性能。
3.1 异步加载
使用异步加载可以在需要并发处理时提高性能:
docs = await loader.aload()
print(docs[0].page_content)
3.2 惰性加载
惰性加载允许我们按需加载数据,而不是一次性加载所有内容:
docs_lazy = loader.lazy_load()
docs = []
for doc in docs_lazy:docs.append(doc)
print(docs[0].page_content)
这些扩展功能使得 JSONLoader
能够灵活应对不同规模和复杂度的 JSON 数据处理需求。