JSON Schema

概述

gpdf 支持完全使用 JSON 定义文档。这适用于:

  • API 驱动的 PDF 生成
  • 从外部数据生成动态文档
  • 无需 Go 代码的模板系统
  • 基于配置的文档创建

基本用法

schema := []byte(`{
    "page": {"size": "A4", "margins": "20mm"},
    "body": [
        {"row": {"cols": [
            {"span": 12, "text": "Hello from JSON!", "style": {"size": 24, "bold": true}}
        ]}}
    ]
}`)

doc, err := template.FromJSON(schema, nil)
if err != nil {
    log.Fatal(err)
}
data, err := doc.Generate()
┌─ A4 ──────────────────────────────────┐
│                                       │
│   Hello from JSON!   ← 24pt, Bold    │
│                                       │
└───────────────────────────────────────┘

使用 Go 模板进行数据绑定

JSON schema 支持 Go 模板表达式以生成动态内容:

schema := []byte(`{
    "page": {"size": "A4", "margins": "20mm"},
    "metadata": {"title": "{{.Title}}"},
    "body": [
        {"row": {"cols": [
            {"span": 12, "text": "{{.Title}}", "style": {"size": 24, "bold": true}}
        ]}},
        {"row": {"cols": [
            {"span": 12, "text": "Author: {{.Author}}"}
        ]}}
    ]
}`)

data := map[string]any{
    "Title":  "Quarterly Report",
    "Author": "ACME Corporation",
}

doc, err := template.FromJSON(schema, data)

Schema 结构

{
    "page": {
        "size": "A4",
        "margins": "20mm"
    },
    "metadata": {
        "title": "Document Title",
        "author": "Author Name",
        "subject": "Subject",
        "creator": "Creator"
    },
    "header": [ /* rows */ ],
    "footer": [ /* rows */ ],
    "body": [ /* rows */ ]
}

页面配置

字段默认值
size"A4", "A3", "Letter", "Legal""A4"
margins尺寸字符串:"20mm", "1in", "15pt"

行和列

{"row": {"cols": [
    {"span": 6, "text": "Left column"},
    {"span": 6, "text": "Right column"}
]}}

完整示例

schema := []byte(`{
    "page": {"size": "A4", "margins": "20mm"},
    "metadata": {"title": "JSON Schema Example", "author": "gpdf"},
    "header": [
        {"row": {"cols": [
            {"span": 6, "text": "gpdf JSON Schema", "style": {"size": 16, "bold": true, "color": "#1A237E"}},
            {"span": 6, "text": "Document Header", "style": {"align": "right", "italic": true}}
        ]}},
        {"row": {"cols": [
            {"span": 12, "line": {"color": "#1A237E", "thickness": "1pt"}}
        ]}}
    ],
    "footer": [
        {"row": {"cols": [
            {"span": 12, "elements": [
                {"type": "line"},
                {"type": "pageNumber", "style": {"align": "center"}}
            ]}
        ]}}
    ],
    "body": [
        {"row": {"cols": [
            {"span": 12, "text": "JSON Schema Generation", "style": {"size": 24, "bold": true}}
        ]}},
        {"row": {"cols": [
            {"span": 12, "spacer": "5mm"}
        ]}},
        {"row": {"cols": [
            {"span": 12, "text": "This PDF was generated from a JSON schema. No Go builder code needed!"}
        ]}},
        {"row": {"cols": [
            {"span": 12, "spacer": "10mm"}
        ]}},
        {"row": {"cols": [
            {"span": 6, "elements": [
                {"type": "text", "content": "Features", "style": {"size": 16, "bold": true}},
                {"type": "list", "list": {"items": [
                    "Declarative document definition",
                    "All element types supported",
                    "Style options",
                    "Header and footer support"
                ]}}
            ]},
            {"span": 6, "elements": [
                {"type": "text", "content": "Supported Elements", "style": {"size": 16, "bold": true}},
                {"type": "list", "list": {"type": "ordered", "items": [
                    "Text with styles",
                    "Tables with headers",
                    "Lists (ordered/unordered)",
                    "Lines and spacers",
                    "QR codes and barcodes",
                    "Images (base64)"
                ]}}
            ]}
        ]}},
        {"row": {"cols": [
            {"span": 12, "spacer": "10mm"}
        ]}},
        {"row": {"cols": [
            {"span": 12, "table": {
                "header": ["Feature", "Format", "Status"],
                "rows": [
                    ["Text styling", "JSON style object", "Supported"],
                    ["Tables", "header + rows arrays", "Supported"],
                    ["Lists", "ordered/unordered", "Supported"],
                    ["Images", "base64 encoded", "Supported"],
                    ["QR codes", "data string", "Supported"],
                    ["Barcodes", "Code128", "Supported"]
                ],
                "columnWidths": [35, 35, 30],
                "headerStyle": {"bold": true, "color": "white", "background": "#1A237E"},
                "stripeColor": "#F5F5F5"
            }}
        ]}},
        {"row": {"cols": [
            {"span": 12, "spacer": "10mm"}
        ]}},
        {"row": {"cols": [
            {"span": 6, "qrcode": {"data": "https://gpdf.dev", "size": "25mm"}},
            {"span": 6, "barcode": {"data": "GPDF-JSON-001", "format": "code128"}}
        ]}}
    ]
}`)

doc, err := template.FromJSON(schema, nil)
┌─ A4 ──────────────────────────────────────────────┐
│  gpdf JSON Schema              Document Header    │  ← header
│  ──────────────────────────────────────────────── │
│                                                   │
│  JSON Schema Generation           ← 24pt bold     │
│                                                   │
│  This PDF was generated from a JSON schema.       │
│                                                   │
│  Features              Supported Elements         │
│  • Declarative...      1. Text with styles        │
│  • All element...      2. Tables with headers     │
│  • Style options       3. Lists                   │
│  • Header/footer       4. Lines and spacers       │
│                        5. QR codes and barcodes    │
│                        6. Images (base64)          │
│                                                   │
│  ┌──────────┬──────────────────┬──────────┐       │
│  │ Feature  │ Format           │ Status   │       │
│  ├──────────┼──────────────────┼──────────┤       │
│  │ Text     │ JSON style obj   │Supported │       │
│  │ Tables   │ header + rows    │Supported │       │
│  │ ...      │ ...              │ ...      │       │
│  └──────────┴──────────────────┴──────────┘       │
│                                                   │
│  ┌────┐        ║║│║║│║║║│║║│                      │
│  │ QR │        GPDF-JSON-001                      │
│  └────┘                                           │
│                                                   │
│  ──────────────────────────────────────────────── │
│                    Page 1                         │  ← footer
└───────────────────────────────────────────────────┘

JSON 中的元素类型

列简写

对于单个元素,可以直接在列上使用简写:

{"span": 12, "text": "Hello", "style": {"bold": true}}
{"span": 12, "spacer": "10mm"}
{"span": 12, "line": {"color": "#FF0000"}}

元素数组

要在一列中放置多个元素,使用 elements 数组:

{"span": 12, "elements": [
    {"type": "text", "content": "Title", "style": {"size": 18, "bold": true}},
    {"type": "spacer", "height": "5mm"},
    {"type": "text", "content": "Body text"},
    {"type": "line"},
    {"type": "pageNumber", "style": {"align": "center"}}
]}

样式对象

{
    "size": 16,
    "bold": true,
    "italic": true,
    "color": "#1A237E",
    "background": "#F5F5F5",
    "align": "center",
    "font": "NotoSansJP"
}
字段类型说明
sizenumber字号(单位:点)
boldboolean粗体
italicboolean斜体
colorstring文本颜色("#RRGGBB""red""blue" 等)
backgroundstring背景颜色
alignstring"left""center""right"
fontstring字体族名称

表格对象

{
    "header": ["Col A", "Col B", "Col C"],
    "rows": [
        ["A1", "B1", "C1"],
        ["A2", "B2", "C2"]
    ],
    "columnWidths": [40, 30, 30],
    "headerStyle": {"bold": true, "color": "white", "background": "#1A237E"},
    "stripeColor": "#F5F5F5"
}

列表对象

{"type": "list", "list": {"items": ["Item 1", "Item 2", "Item 3"]}}
{"type": "list", "list": {"type": "ordered", "items": ["First", "Second", "Third"]}}

二维码对象

{"span": 6, "qrcode": {"data": "https://gpdf.dev", "size": "25mm"}}

条形码对象

{"span": 6, "barcode": {"data": "INV-001", "format": "code128"}}

绝对定位

将元素放置在精确的 XY 坐标处,脱离常规网格流:

{
    "absolute": [
        {
            "x": "120mm",
            "y": "20mm",
            "elements": [
                {"type": "text", "content": "CONFIDENTIAL", "style": {"size": 20, "bold": true, "color": "red"}}
            ]
        },
        {
            "x": "10mm",
            "y": "250mm",
            "width": "25mm",
            "height": "25mm",
            "elements": [
                {"type": "qrcode", "qrcode": {"data": "https://gpdf.dev", "size": "20mm"}}
            ]
        },
        {
            "x": "0mm",
            "y": "0mm",
            "origin": "page",
            "elements": [
                {"type": "text", "content": "Page origin"}
            ]
        }
    ]
}

absolute 数组可以出现在顶层(应用到所有页面)或单独的页面定义中。

字段类型必填说明
xstringX 坐标(尺寸字符串)
ystringY 坐标(尺寸字符串)
widthstring显式宽度(默认:剩余空间)
heightstring显式高度(默认:剩余空间)
originstring"content"(默认)或 "page"
elementsarray元素对象数组

尺寸字符串

格式示例
毫米"20mm"
"12pt"
厘米"2.5cm"
英寸"1in"

命名颜色

JSON schema 支持命名颜色:"red""green""blue""yellow""cyan""magenta""black""white""gray"

也可以使用十六进制格式:"#FF6B6B""#1A237E"

结合 Go 选项

使用 Go 选项覆盖或扩展 JSON schema:

fontData, _ := os.ReadFile("fonts/NotoSansJP-Regular.ttf")

doc, err := template.FromJSON(schema, data,
    template.WithFont("NotoSansJP", fontData),
    template.WithDefaultFont("NotoSansJP", 12),
)