商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 使用Python实现将JSON数据生成PDF文档

使用Python实现将JSON数据生成PDF文档

  发布于2026-07-11 阅读(0)

扫一扫,手机访问

在企业日常运营中,JSON格式的数据几乎无处不在——API接口、配置文件、数据交换,几乎都离不开它。但问题来了:如何把这些结构化的JSON数据,变成一份拿得出手的PDF报告?很多人第一反应是手动复制粘贴,或者搬出复杂的模板工具。结果呢?效率低不说,格式还容易跑偏,数据也容易漏掉。尤其是那些需要定期生成的财务报表、项目进度报告、客户信息汇总,自动化生成PDF成了刚需。

使用Python实现将JSON数据生成PDF文档

这篇文章就来讲讲,怎么用Python把JSON数据自动转成格式规整的PDF文档。整个过程全自动化,不需要人工插手,适用于业务报表生成、数据归档、合同附件制作、API数据可视化等场景。通过代码,你可以灵活控制文档布局、字体样式、表格结构和页面元素,保证生成的PDF既专业又美观。

实现这个功能,需要用到Free Spire.PDF for Python这个库。安装很简单,一行命令搞定:

pip install spire.pdf.free

1. 准备 JSON 数据并创建 PDF 文档

在生成PDF之前,先得准备好JSON数据,并初始化PDF文档对象。这里用一份销售数据报告做例子,包含产品信息、销售记录和统计摘要。

import json
from spire.pdf import PdfDocument, PdfPageBase
from spire.pdf.graphics import *
# 示例 JSON 数据
json_data = """
{
    "report_title": "2024年第一季度销售报告",
    "company": "ABC科技有限公司",
    "date": "2024-03-31",
    "summary": {
        "total_sales": 1580000,
        "total_orders": 342,
        "a verage_order_value": 4619.88
    },
    "products": [
        {"name": "笔记本电脑", "category": "电子产品", "quantity": 120, "unit_price": 5999, "total": 719880},
        {"name": "无线鼠标", "category": "配件", "quantity": 450, "unit_price": 89, "total": 40050},
        {"name": "机械键盘", "category": "配件", "quantity": 280, "unit_price": 399, "total": 111720},
        {"name": "显示器", "category": "电子产品", "quantity": 95, "unit_price": 2499, "total": 237405},
        {"name": "USB集线器", "category": "配件", "quantity": 600, "unit_price": 59, "total": 35400}
    ]
}
"""
# 解析 JSON 数据
data = json.loads(json_data)
# 创建 PDF 文档
doc = PdfDocument()
page = doc.Pages.Add()

说明:

  • json.loads() 把JSON字符串转成Python字典,方便后面提取数据。
  • PdfDocument() 创建PDF文档对象,Pages.Add() 添加新页面作为内容载体。
  • 示例数据包含了报告标题、公司信息、统计摘要和产品列表,模拟的是真实业务场景。

这一步完成数据准备和文档初始化,为后续内容绘制打好基础。

2. 绘制文档标题和公司信息

接下来,在PDF页面顶部画上报告标题和公司基本信息,搭起文档的整体框架。

def draw_header(page, data):
    """绘制文档标题和公司信息"""
    # 设置页面边距
    margin_left = 50
    margin_top = 50
    y_position = margin_top
    
    # 绘制公司标题
    company_font = PdfTrueTypeFont("Arial", 14.0, PdfFontStyle.Bold, True)
    company_brush = PdfSolidBrush(PdfRGBColor(Color.get_DarkGray()))
    page.Canvas.DrawString(
        data["company"], 
        company_font, 
        company_brush, 
        margin_left, 
        y_position
    )
    y_position += 25
    
    # 绘制报告标题
    title_font = PdfTrueTypeFont("Arial", 24.0, PdfFontStyle.Bold, True)
    title_brush = PdfSolidBrush(PdfRGBColor(Color.get_Na vy()))
    title_format = PdfStringFormat(PdfTextAlignment.Left)
    page.Canvas.DrawString(
        data["report_title"], 
        title_font, 
        title_brush, 
        margin_left, 
        y_position, 
        title_format
    )
    y_position += 35
    
    # 绘制日期
    date_font = PdfTrueTypeFont("Arial", 11.0, PdfFontStyle.Regular, True)
    date_brush = PdfSolidBrush(PdfRGBColor(Color.get_Gray()))
    page.Canvas.DrawString(
        f"报告日期:{data['date']}", 
        date_font, 
        date_brush, 
        margin_left, 
        y_position
    )
    
    return y_position + 30

# 调用函数绘制头部
current_y = draw_header(page, data)

说明:

  • PdfTrueTypeFont 用来设置字体类型、大小和样式(比如粗体、斜体)。
  • PdfSolidBrush 定义文本颜色,支持RGB色彩空间。
  • DrawString 方法在指定坐标位置绘制文本,可以配合 PdfStringFormat 设置对齐方式。
  • 通过递增 y_position 变量,实现内容的垂直布局,避免重叠。

这一步建立了文档的视觉层次,让读者一眼就能了解报告的基本信息。

3. 绘制统计摘要信息

标题下面,展示关键的业务统计数据,用简洁的方式呈现核心指标。

def draw_summary(page, data, y_position):
    """绘制统计摘要"""
    margin_left = 50
    summary = data["summary"]
    
    # 绘制摘要标题
    section_font = PdfTrueTypeFont("Arial", 16.0, PdfFontStyle.Bold, True)
    section_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    page.Canvas.DrawString(
        "销售摘要", 
        section_font, 
        section_brush, 
        margin_left, 
        y_position
    )
    y_position += 30
    
    # 绘制摘要内容
    content_font = PdfTrueTypeFont("Arial", 11.0, PdfFontStyle.Regular, True)
    content_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    
    summary_items = [
        f"总销售额:¥{summary['total_sales']:,.2f}",
        f"订单总数:{summary['total_orders']}",
        f"平均订单价值:¥{summary['a verage_order_value']:,.2f}"
    ]
    
    for item in summary_items:
        page.Canvas.DrawString(
            item, 
            content_font, 
            content_brush, 
            margin_left, 
            y_position
        )
        y_position += 22
    
    return y_position + 20

# 调用函数绘制摘要
current_y = draw_summary(page, data, current_y)

说明:

  • 用f-string格式化数字,:, 添加千位分隔符,.2f 保留两位小数。
  • 摘要信息逐行排列,每条间隔22个单位,保持视觉舒适度。
  • 字体大小略小于标题,但大于正文,形成清晰的信息层级。

这部分突出了报告的核心数据,帮助读者快速把握业务概况。

4. 创建产品明细表格

表格是展示结构化数据的最佳方式。我们把JSON里的产品列表转成PDF表格,包含表头和数据行。

def draw_product_table(page, data, y_position):
    """绘制产品明细表格"""
    margin_left = 50
    products = data["products"]
    
    # 绘制表格标题
    table_title_font = PdfTrueTypeFont("Arial", 16.0, PdfFontStyle.Bold, True)
    table_title_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    page.Canvas.DrawString(
        "产品明细", 
        table_title_font, 
        table_title_brush, 
        margin_left, 
        y_position
    )
    y_position += 30
    
    # 定义表格列
    columns = ["产品名称", "类别", "数量", "单价", "总价"]
    column_widths = [120, 100, 80, 100, 100]
    
    # 绘制表头
    header_font = PdfTrueTypeFont("Arial", 11.0, PdfFontStyle.Bold, True)
    header_brush = PdfSolidBrush(PdfRGBColor(Color.get_White()))
    header_bg_brush = PdfSolidBrush(PdfRGBColor(Color.get_Na vy()))
    
    x_position = margin_left
    for i, col in enumerate(columns):
        # 绘制表头背景
        rect = RectangleF(x_position, y_position, column_widths[i], 25)
        page.Canvas.DrawRectangle(header_bg_brush, rect)
        # 绘制表头文本
        page.Canvas.DrawString(
            col, 
            header_font, 
            header_brush, 
            x_position + 5, 
            y_position + 5
        )
        x_position += column_widths[i]
    
    y_position += 25
    
    # 绘制数据行
    row_font = PdfTrueTypeFont("Arial", 10.0, PdfFontStyle.Regular, True)
    row_brush = PdfSolidBrush(PdfRGBColor(Color.get_Black()))
    alternate_brush = PdfSolidBrush(PdfRGBColor(Color.get_LightGray()))
    
    for idx, product in enumerate(products):
        # 交替行背景色
        if idx % 2 == 0:
            bg_brush = PdfSolidBrush(PdfRGBColor(Color.get_White()))
        else:
            bg_brush = alternate_brush
        
        x_position = margin_left
        row_height = 22
        
        # 绘制行背景
        row_rect = RectangleF(margin_left, y_position, sum(column_widths), row_height)
        page.Canvas.DrawRectangle(bg_brush, row_rect)
        
        # 绘制单元格数据
        cell_data = [
            product["name"],
            product["category"],
            str(product["quantity"]),
            f"¥{product['unit_price']:,}",
            f"¥{product['total']:,}"
        ]
        
        for i, cell_value in enumerate(cell_data):
            page.Canvas.DrawString(
                cell_value, 
                row_font, 
                row_brush, 
                x_position + 5, 
                y_position + 4
            )
            x_position += column_widths[i]
        
        y_position += row_height
    
    # 绘制表格边框
    border_pen = PdfPen(PdfRGBColor(Color.get_Black()), 0.5)
    table_width = sum(column_widths)
    table_height = 25 + len(products) * 22
    
    # 外边框
    page.Canvas.DrawRectangle(
        border_pen, 
        RectangleF(margin_left, y_position - table_height, table_width, table_height)
    )
    
    # 横线
    for i in range(len(products) + 2):
        line_y = y_position - table_height + i * 22 if i > 0 else y_position - table_height
        if i == 0:
            line_y = y_position - table_height
        elif i == 1:
            line_y = y_position - table_height + 25
        else:
            line_y = y_position - table_height + 25 + (i - 1) * 22
        
        page.Canvas.DrawLine(
            border_pen, 
            margin_left, 
            line_y, 
            margin_left + table_width, 
            line_y
        )
    
    # 竖线
    x_pos = margin_left
    for width in column_widths:
        page.Canvas.DrawLine(
            border_pen, 
            x_pos, 
            y_position - table_height, 
            x_pos, 
            y_position
        )
        x_pos += width
    page.Canvas.DrawLine(
        border_pen, 
        x_pos, 
        y_position - table_height, 
        x_pos, 
        y_position
    )
    
    return y_position + 30

# 调用函数绘制表格
current_y = draw_product_table(page, data, current_y)

说明:

  • 表头用了深色背景加白色文字,可读性更强。
  • 数据行用了交替背景色(白色和浅灰色),视觉上更容易区分。
  • RectangleF 用来绘制矩形区域,作为单元格背景和边框。
  • DrawLine 方法绘制表格的横线和竖线,形成完整的网格结构。
  • 列宽根据内容长度合理分配,确保数据显示完整且不拥挤。

这一步把JSON数组转成结构化的表格,是数据可视化的核心环节。

5. 添加页脚信息

最后,在页面底部加上页脚,包含页码和版权信息,让文档更完整、更专业。

def draw_footer(page, page_number, total_pages):
    """绘制页脚"""
    page_width = page.Canvas.ClientSize.Width
    margin_bottom = 30
    
    # 绘制分隔线
    line_pen = PdfPen(PdfRGBColor(Color.get_LightGray()), 0.5)
    page.Canvas.DrawLine(
        line_pen, 
        50, 
        page.Canvas.ClientSize.Height - margin_bottom - 15, 
        page_width - 50, 
        page.Canvas.ClientSize.Height - margin_bottom - 15
    )
    
    # 绘制页码
    footer_font = PdfTrueTypeFont("Arial", 9.0, PdfFontStyle.Regular, True)
    footer_brush = PdfSolidBrush(PdfRGBColor(Color.get_Gray()))
    footer_format = PdfStringFormat(PdfTextAlignment.Center)
    
    page_text = f"第 {page_number} 页 / 共 {total_pages} 页"
    page.Canvas.DrawString(
        page_text, 
        footer_font, 
        footer_brush, 
        page_width / 2, 
        page.Canvas.ClientSize.Height - margin_bottom, 
        footer_format
    )
    
    # 绘制版权信息
    copyright_text = "© 2024 ABC科技有限公司 - 内部资料,请勿外传"
    page.Canvas.DrawString(
        copyright_text, 
        footer_font, 
        footer_brush, 
        page_width / 2, 
        page.Canvas.ClientSize.Height - margin_bottom + 15, 
        footer_format
    )

# 调用函数绘制页脚(单页文档)
draw_footer(page, 1, 1)

说明:

  • 页脚包含水平分隔线、页码和版权声明,符合商业文档的规范。
  • 使用居中对齐,让页脚在视觉上平衡美观。
  • 字体较小且颜色较浅,避免干扰主要内容阅读。

6. 保存 PDF 文档

所有内容绘制完成后,保存PDF文件到指定路径。

output_file = "销售报告.pdf"
doc.Sa veToFile(output_file)
doc.Close()

print(f"PDF 文档已生成:{output_file}")

说明:

  • Sa veToFile 方法把内存中的PDF文档保存到文件系统。
  • Close 方法释放文档资源,确保文件完整性。
  • 生成的PDF可以直接打开查看、打印或通过邮件发送。

关键类与方法解析

为了方便查阅和扩展,下面整理了本文使用的核心类、方法和属性。

主要类说明

类名说明
PdfDocumentPDF 文档对象,管理整个文档的生命周期
PdfPageBase页面对象,提供画布用于绘制内容
PdfTrueTypeFont字体类,设置字体名称、大小、样式
PdfSolidBrush画刷类,定义填充颜色
PdfPen画笔类,定义线条颜色和宽度
PdfStringFormat文本格式类,设置对齐方式、字符间距等
RectangleF矩形结构,用于定义绘制区域
PdfRGBColor颜色类,支持 RGB 色彩模式

常用方法说明

方法说明参数示例
doc.Pages.Add()添加新页面
page.Canvas.DrawString()在画布上绘制文本(text, font, brush, x, y, format)
page.Canvas.DrawRectangle()绘制矩形(填充或边框)(brush/pen, rectangle)
page.Canvas.DrawLine()绘制直线(pen, x1, y1, x2, y2)
doc.Sa veToFile()保存文档到文件(filename)
doc.Close()关闭文档并释放资源

字体与样式设置

# 创建字体
font = PdfTrueTypeFont("Arial", 12.0, PdfFontStyle.Bold, True)
# 参数:字体名称、字号、样式(Bold/Italic/Regular/Underline)、是否嵌入

# 创建画刷
brush = PdfSolidBrush(PdfRGBColor(Color.get_Na vy()))
# 支持的颜色:get_Black(), get_White(), get_Red(), get_Blue(), get_Na vy() 等

# 创建画笔
pen = PdfPen(PdfRGBColor(Color.get_Black()), 0.5)
# 参数:颜色、线条宽度

# 设置文本格式
format = PdfStringFormat(PdfTextAlignment.Center, PdfVerticalAlignment.Middle)
# 对齐方式:Left, Center, Right, Justify

布局技巧

  • 垂直布局:通过递增 y 坐标实现内容从上到下排列
  • 水平布局:通过递增 x 坐标实现内容从左到右排列
  • 边距控制:设置 margin_leftmargin_top 等变量统一管理边距
  • 间距调整:根据字体高度和内容重要性调整行间距

扩展应用场景

基于本文的基础实现,还可以进一步扩展功能:

1. 多页文档支持

当数据量较大时,需要自动分页:

# 检测内容是否超出页面高度
if current_y > page.Canvas.ClientSize.Height - 100:
    page = doc.Pages.Add()  # 添加新页面
    current_y = 50  # 重置 y 坐标

2. 从文件读取 JSON

with open('sales_data.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

3. 添加图表可视化

结合 Spire.PDF 的图形功能,可以绘制柱状图、饼图等:

# 绘制简单柱状图
for i, product in enumerate(products):
    bar_height = product['total'] / 10000  # 缩放比例
    bar_rect = RectangleF(margin_left + i * 60, chart_y, 50, bar_height)
    page.Canvas.DrawRectangle(bar_brush, bar_rect)

4. 批量生成报告

遍历多个 JSON 文件,为不同部门或时间段生成独立报告:

import glob
for json_file in glob.glob('reports/*.json'):
    with open(json_file, 'r') as f:
        data = json.load(f)
    generate_pdf(data, f"report_{json_file}.pdf")

5. 自定义模板系统

将布局逻辑封装为模板类,支持动态配置:

class PDFTemplate:
    def __init__(self, config):
        self.font_config = config['fonts']
        self.color_scheme = config['colors']
        self.layout = config['layout']
    
    def render(self, data):
        # 根据配置渲染 PDF
        pass

总结

通过本文的示例,你已经掌握了如何用Python从JSON数据自动生成专业的PDF文档。从解析JSON数据结构,到绘制标题、摘要、表格和页脚,整个流程完全自动化,特别适用于业务报表、数据归档和文档分发场景。

比起手动制作PDF,代码方式有几个明显的优势:

  • 高效性:一键生成,不用重复劳动
  • 一致性:统一的格式和样式,保证专业形象
  • 灵活性:可根据数据动态调整内容和布局
  • 可扩展性:轻松集成到现有系统或工作流中

你可以在此基础上继续探索更多高级功能,比如添加水印、加密文档、插入图像、生成目录等,为企业级文档自动化提供完整解决方案。如果你正在处理大量结构化数据,或者需要定期生成标准化报告,这种基于Python和Spire.PDF的方案,能大大提升工作效率。

本文转载于:https://www.jb51.net/python/3672408m8.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注