118 lines
5.5 KiB
Python
118 lines
5.5 KiB
Python
import re
|
||
import os
|
||
import json
|
||
|
||
def extract_and_save_json_schemas(markdown_file_path, output_directory="json_schemas"):
|
||
"""
|
||
从 Markdown 文件中提取 JSON Schema 并将其保存到单独文件的函数。
|
||
|
||
Args:
|
||
markdown_file_path (str): 输入 Markdown 文件的路径。
|
||
output_directory (str): 用于保存 JSON Schema 文件的目录。
|
||
默认是 "json_schemas"。
|
||
"""
|
||
try:
|
||
with open(markdown_file_path, 'r', encoding='utf-8') as f:
|
||
markdown_content = f.read()
|
||
except FileNotFoundError:
|
||
print(f"错误:文件 '{markdown_file_path}' 未找到。")
|
||
return
|
||
except Exception as e:
|
||
print(f"错误:读取文件 '{markdown_file_path}' 时发生错误: {e}")
|
||
return
|
||
|
||
# 用于提取 JSON 代码块的正则表达式
|
||
# 搜索以 ```json (或 ```Json 等,不区分大小写) 开头,并以 ``` 结尾的代码块
|
||
# 代码块内容应为 { 到 },并能被 json.loads 解析
|
||
# re.DOTALL (或 re.S) 使 '.' 能够匹配包括换行符在内的任意字符
|
||
# *? 用于非贪婪匹配
|
||
json_block_pattern = r"```[Jj][Ss][Oo][Nn]\s*(\{[\s\S]*?\})\s*```"
|
||
|
||
json_schemas_found = re.findall(json_block_pattern, markdown_content)
|
||
|
||
if not json_schemas_found:
|
||
print("未找到 JSON Schema 代码块。")
|
||
return
|
||
|
||
if not os.path.exists(output_directory):
|
||
try:
|
||
os.makedirs(output_directory)
|
||
print(f"目录 '{output_directory}' 已创建。")
|
||
except Exception as e:
|
||
print(f"错误:创建目录 '{output_directory}' 失败: {e}")
|
||
return
|
||
|
||
saved_files_count = 0
|
||
for i, schema_str in enumerate(json_schemas_found):
|
||
try:
|
||
# 解析 JSON 字符串以获取 $id 或 title
|
||
schema_json_data = json.loads(schema_str)
|
||
|
||
file_name = None
|
||
# 尝试从 $id 获取文件名
|
||
if isinstance(schema_json_data, dict) and '$id' in schema_json_data:
|
||
id_value = schema_json_data['$id']
|
||
if isinstance(id_value, str) and id_value.strip():
|
||
# 使用 URL 的最后一部分作为文件名
|
||
file_name_candidate = id_value.split('/')[-1]
|
||
# 避免文件名为空的情况
|
||
if file_name_candidate.strip():
|
||
file_name = file_name_candidate
|
||
if not file_name.endswith('.json'): # 确保以 .json 结尾
|
||
file_name += '.json'
|
||
|
||
# 如果 $id 不可用或无效,则尝试从 title 生成文件名
|
||
if not file_name and isinstance(schema_json_data, dict) and 'title' in schema_json_data:
|
||
title_value = schema_json_data['title']
|
||
if isinstance(title_value, str) and title_value.strip():
|
||
# 替换或删除文件名中不合适的字符 (例如: \ / * ? : " < > | 和空格)
|
||
safe_title = re.sub(r'[\\/*?:"<>|\s]', "_", title_value) # 将不合法字符和空格替换为下划线
|
||
safe_title = re.sub(r'_+', "_", safe_title) # 将连续的下划线替换为单个下划线
|
||
file_name = f"{safe_title}.json"
|
||
|
||
# 如果文件名仍未确定,则使用序号
|
||
if not file_name:
|
||
file_name = f"schema_{i+1}.json"
|
||
|
||
output_file_path = os.path.join(output_directory, file_name)
|
||
|
||
try:
|
||
with open(output_file_path, 'w', encoding='utf-8') as outfile:
|
||
# 使用 json.dump 进行格式化并写出,ensure_ascii=False 以正确处理中文等非ASCII字符
|
||
json.dump(schema_json_data, outfile, ensure_ascii=False, indent=4)
|
||
print(f"Schema 已保存至 '{output_file_path}'。")
|
||
saved_files_count += 1
|
||
except Exception as e:
|
||
print(f"错误:写入文件 '{output_file_path}' 时发生错误: {e}")
|
||
|
||
except json.JSONDecodeError as e:
|
||
print(f"警告:第 {i+1} 个 JSON Schema 解析失败。已跳过。")
|
||
# 如果需要调试,可以取消下面这行注释来打印有问题的代码块开头部分
|
||
print(f"问题代码块开头:\n{schema_str[:200]}...")
|
||
print(f"问题:{e}")
|
||
continue
|
||
except Exception as e:
|
||
print(f"警告:处理第 {i+1} 个 JSON Schema 时发生意外错误: {e}")
|
||
continue
|
||
|
||
if saved_files_count > 0:
|
||
print(f"\n总共保存了 {saved_files_count} 个 JSON Schema 文件。")
|
||
else:
|
||
print("\n未能保存任何 JSON Schema 文件。")
|
||
|
||
# --- 使用方法 ---
|
||
if __name__ == "__main__":
|
||
# 请在此处指定您的 Markdown 文件的路径
|
||
markdown_file = "/Users/zpc01/workspace/zzlh/compliance/assets/doc/交换模型schema示例.md" # 例如: "models.md"
|
||
|
||
# 输出目录(可选)
|
||
# 如果省略,将在脚本所在目录下创建名为 "extracted_json_schemas" 的目录
|
||
output_dir = "/Users/zpc01/workspace/zzlh/compliance/assets/doc/extracted_schemas"
|
||
|
||
# 执行函数
|
||
# 在执行前,请确保 markdown_file 变量指向一个存在的 Markdown 文件。
|
||
if os.path.exists(markdown_file):
|
||
extract_and_save_json_schemas(markdown_file, output_dir)
|
||
else:
|
||
print(f"指定的 Markdown 文件 '{markdown_file}' 不存在。")
|
||
print("请将脚本中的 `markdown_file` 变量更新为正确的Markdown文件路径。") |