JSON 스키마

개요

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 스키마는 동적 콘텐츠를 위한 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)

스키마 구조

{
    "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    │  ← 머리글
│  ──────────────────────────────────────────────── │
│                                                   │
│  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                         │  ← 바닥글
└───────────────────────────────────────────────────┘

JSON의 요소 타입

열 축약형

단일 요소의 경우, 열에 직접 축약형을 사용합니다:

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

Elements 배열

하나의 열에 여러 요소를 넣으려면 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"}}
]}

Style 객체

{
    "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폰트 패밀리 이름

Table 객체

{
    "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"
}

List 객체

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

QR Code 객체

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

Barcode 객체

{"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 배열은 최상위 레벨(모든 페이지에 적용) 또는 개별 페이지 정의 내부에 나타날 수 있습니다.

필드타입필수설명
xstringYesX 좌표 (치수 문자열)
ystringYesY 좌표 (치수 문자열)
widthstringNo명시적 너비 (기본값: 남은 공간)
heightstringNo명시적 높이 (기본값: 남은 공간)
originstringNo"content" (기본값) 또는 "page"
elementsarrayYes요소 객체 배열

치수 문자열

형식예시
밀리미터"20mm"
포인트"12pt"
센티미터"2.5cm"
인치"1in"

이름 있는 색상

JSON 스키마는 이름 있는 색상을 지원합니다: "red", "green", "blue", "yellow", "cyan", "magenta", "black", "white", "gray".

또는 hex 형식을 사용합니다: "#FF6B6B", "#1A237E".

Go 옵션과 결합

Go 옵션으로 JSON 스키마를 재정의하거나 확장합니다:

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

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