用fastapi将.md文件转为json文件

在 FastAPI 中实现将 .md文件转换为 JSON 文件非常简单,我们可以利用 Python 的 frontmatter库(或 python-frontmatter)来解析 Markdown 文件的 Front Matter(元数据)和内容。以下是完整的实现步骤:


​方法1:一次性转换所有 .md文件(适用于静态博客 API)​​

​1. 安装依赖​

首先安装必要的库:

pip install fastapi python-frontmatter uvicorn

2. 创建 FastAPI 应用​​

假设你的 Markdown 文件存放在 ./blog-posts/目录下,结构如下:

/blog-posts/ ├── post1.md ├── post2.md └── ... 创建一个 FastAPI 应用 main.py:

from fastapi import FastAPI
import frontmatter
import glob
import json
from pathlib import Path
from typing import List, Dict

app = FastAPI()

存储 Markdown 文件的目录

MARKDOWN_DIR = "./blog-posts"

@app.get("/convert-md-to-json", response_model=List[Dict])
async def convert_md_to_json():
    """将所有 Markdown 文件转换为 JSON 并返回"""
    md_files = glob.glob(f"{MARKDOWN_DIR}/*.md")
    posts = []

    for md_file in md_files:
        # 解析 Markdown 文件
        post = frontmatter.load(md_file)

        # 提取文件名(作为 slug)
        slug = Path(md_file).stem

        # 组合数据
        post_data = {
            "slug": slug,
            **post.metadata,  # 展开 Front Matter(title, date, tags...)
            "content": post.content,  # Markdown 正文
        }
        posts.append(post_data)

    # 可选:保存到 JSON 文件
    with open("blog_posts.json", "w", encoding="utf-8") as f:
        json.dump(posts, f, ensure_ascii=False, indent=2)

    return posts

​3. 运行 FastAPI​​

uvicorn main:app --reload

访问 http://127.0.0.1:8000/convert-md-to-json,你会得到类似这样的 JSON 响应:

[
  {
    "slug": "post1",
    "title": "我的第一篇博客",
    "date": "2023-10-01",
    "tags": ["技术", "Python"],
    "content": "这是博客正文..."
  },
  {
    "slug": "post2",
    "title": "FastAPI 教程",
    "date": "2023-10-02",
    "tags": ["后端"],
    "content": "FastAPI 是一个现代框架..."
  }
]

​4. 额外功能​​

​​自动保存 JSON 文件​​:代码中已经包含 json.dump(),运行后会在当前目录生成 blog_posts.json。

​​按需转换单个文件​​:可以增加一个 API 端点,传入文件名,返回单个转换后的 JSON。

​​方法 2:动态转换(按需解析 .md文件)​​

如果你想在请求时动态解析 .md文件并返回 JSON(而不是预先转换),可以这样修改:

from fastapi import FastAPI, HTTPException
import frontmatter
from pathlib import Path

app = FastAPI()

MARKDOWN_DIR = "./blog-posts"

@app.get("/posts/{slug}")
async def get_post(slug: str):
    """根据 slug 获取单篇博客内容"""
    md_file = Path(MARKDOWN_DIR) / f"{slug}.md"

    if not md_file.exists():
        raise HTTPException(status_code=404, detail="Post not found")

    post = frontmatter.load(md_file)

    return {
        "slug": slug,
        **post.metadata,
        "content": post.content,
    }

访问 http://127.0.0.1:8000/posts/post1会返回:

{
  "slug": "post1",
  "title": "我的第一篇博客",
  "date": "2023-10-01",
  "tags": ["技术", "Python"],
  "content": "这是博客正文..."
}

​方法 3:结合文件监听(自动更新 JSON)​​

如果你希望每次 .md文件变化时自动更新 JSON,可以使用 watchdog库监听文件变化:

​1. 安装 watchdog​​ pip install watchdog ​​2. 创建文件监听脚本 watcher.py​​

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import frontmatter
import glob
import json
from pathlib import Path

MARKDOWN_DIR = "./blog-posts"
OUTPUT_JSON = "blog_posts.json"

def convert_md_to_json():
    md_files = glob.glob(f"{MARKDOWN_DIR}/*.md")
    posts = []

    for md_file in md_files:
        post = frontmatter.load(md_file)
        slug = Path(md_file).stem
        posts.append({
            "slug": slug,
            **post.metadata,
            "content": post.content,
        })

    with open(OUTPUT_JSON, "w", encoding="utf-8") as f:
        json.dump(posts, f, ensure_ascii=False, indent=2)
    print(f"✅ Updated {OUTPUT_JSON}")

class MarkdownHandler(FileSystemEventHandler):
    def on_modified(self, event):
        if event.src_path.endswith(".md"):
            convert_md_to_json()

if __name__ == "__main__":
    event_handler = MarkdownHandler()
    observer = Observer()
    observer.schedule(event_handler, MARKDOWN_DIR, recursive=True)
    observer.start()
    print(f"👀 Watching {MARKDOWN_DIR} for changes...")

    try:
        while True:
            pass
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

​3. 运行监听​​

python watcher.py 现在,每次修改或新增 .md文件,blog_posts.json都会自动更新。

​​总结​​ 方法 适用场景 优点 缺点


​方法 1(一次性转换)​​

静态博客生成、批量转换简单直接,适合预生成数据需要手动触发或结合 CI/CD​​方法 2(动态解析)​​动态博客 API、按需读取实时解析,无需存储 JSON每次请求都要解析文件​​方法 3(监听文件)​​本地开发、自动更新自动同步,适合写作流程需要额外运行监听脚本


​推荐方案:​​

如果是​​静态博客​​,使用方法 1 或 3,预生成 JSON。
如果是​​动态博客 API​​,使用方法 2,按需解析。
希望这能帮到你!🚀