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"
}
| 필드 | 타입 | 설명 |
|---|---|---|
size | number | 폰트 크기 (포인트) |
bold | boolean | 굵게 |
italic | boolean | 기울임꼴 |
color | string | 텍스트 색상 ("#RRGGBB", "red", "blue" 등) |
background | string | 배경 색상 |
align | string | "left", "center", "right" |
font | string | 폰트 패밀리 이름 |
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 배열은 최상위 레벨(모든 페이지에 적용) 또는 개별 페이지 정의 내부에 나타날 수 있습니다.
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
x | string | Yes | X 좌표 (치수 문자열) |
y | string | Yes | Y 좌표 (치수 문자열) |
width | string | No | 명시적 너비 (기본값: 남은 공간) |
height | string | No | 명시적 높이 (기본값: 남은 공간) |
origin | string | No | "content" (기본값) 또는 "page" |
elements | array | Yes | 요소 객체 배열 |
치수 문자열
| 형식 | 예시 |
|---|---|
| 밀리미터 | "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),
)