JSON Schema
Visao Geral
gpdf suporta a definicao de documentos inteiramente em JSON. Isso e ideal para:
- Geracao de PDF orientada por API
- Documentos dinamicos a partir de dados externos
- Sistemas de templates sem codigo Go
- Criacao de documentos baseada em configuracao
Uso Basico
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 │
│ │
└───────────────────────────────────────┘
Vinculacao de Dados com Go Templates
JSON schemas suportam expressoes Go template para conteudo dinamico:
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)
Estrutura do Schema
{
"page": {
"size": "A4",
"margins": "20mm"
},
"metadata": {
"title": "Document Title",
"author": "Author Name",
"subject": "Subject",
"creator": "Creator"
},
"header": [ /* rows */ ],
"footer": [ /* rows */ ],
"body": [ /* rows */ ]
}
Configuracao de Pagina
| Campo | Valores | Padrao |
|---|---|---|
size | "A4", "A3", "Letter", "Legal" | "A4" |
margins | String de dimensao: "20mm", "1in", "15pt" | — |
Linhas e Colunas
{"row": {"cols": [
{"span": 6, "text": "Left column"},
{"span": 6, "text": "Right column"}
]}}
Exemplo Completo
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 │ ← cabecalho
│ ──────────────────────────────────────────────── │
│ │
│ 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 │ ← rodape
└───────────────────────────────────────────────────┘
Tipos de Elementos em JSON
Atalho de Coluna
Para elementos unicos, use o atalho diretamente na coluna:
{"span": 12, "text": "Hello", "style": {"bold": true}}
{"span": 12, "spacer": "10mm"}
{"span": 12, "line": {"color": "#FF0000"}}
Array de Elementos
Para multiplos elementos em uma coluna, use o array 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"}}
]}
Objeto Style
{
"size": 16,
"bold": true,
"italic": true,
"color": "#1A237E",
"background": "#F5F5F5",
"align": "center",
"font": "NotoSansJP"
}
| Campo | Tipo | Descricao |
|---|---|---|
size | number | Tamanho da fonte em pontos |
bold | boolean | Peso negrito |
italic | boolean | Estilo italico |
color | string | Cor do texto ("#RRGGBB", "red", "blue", etc.) |
background | string | Cor de fundo |
align | string | "left", "center", "right" |
font | string | Nome da familia de fonte |
Objeto Table
{
"header": ["Col A", "Col B", "Col C"],
"rows": [
["A1", "B1", "C1"],
["A2", "B2", "C2"]
],
"columnWidths": [40, 30, 30],
"columnAlign": ["left", "right", "right"],
"headerStyle": {"bold": true, "color": "white", "background": "#1A237E"},
"stripeColor": "#F5F5F5",
"border": {"width": "1pt", "color": "#1A237E"},
"cellBorder": {"width": "0.5pt", "color": "gray(0.5)", "style": "dashed"},
"borderCollapse": true,
"background": "#FAFAFA"
}
Since v1.0.10 columnAlign define o alinhamento horizontal por coluna ("left" / "center" / "right") e se aplica ao cabecalho e ao corpo. Colunas sem entrada usam o alinhamento a esquerda padrao.
Since v1.0.7 border desenha uma moldura externa, cellBorder adiciona a mesma borda ao redor de cada celula de cabecalho + corpo (linhas de grade), borderCollapse colapsa bordas de celulas adjacentes e background preenche a caixa externa da tabela. A estrutura de border / cellBorder esta descrita em Objeto Border.
Objeto Image
{"span": 6, "image": {
"src": "data:image/png;base64,...",
"width": "60mm",
"minWidth": "40mm",
"border": {"widths": ["2pt", "2pt", "2pt", "2pt"], "color": "#E53935"},
"background": "#FFF8E1"
}}
| Campo | Descricao |
|---|---|
src | base64 / data URI / caminho de arquivo |
width / height | Dimensao de exibicao |
minWidth / minHeight | Since v1.0.6 Transborda para a proxima pagina quando seria necessario reduzir abaixo deste valor |
fit | "contain" (padrao), "cover", "stretch", "original" |
align | "left", "center", "right" |
border | Since v1.0.7 Borda ao redor da imagem (ver Objeto Border) |
background | Since v1.0.7 Cor de fundo atras da imagem (util para PNG transparente) |
Objeto Border
Since v1.0.7Usado por table.border, table.cellBorder e image.border:
{
"width": "1pt",
"color": "#1A237E",
"style": "solid"
}
Para larguras por lado em ordem CSS (top, right, bottom, left), use widths em vez de width:
{"widths": ["2pt", "1pt", "2pt", "1pt"], "color": "#1A237E", "style": "dashed"}
| Campo | Tipo | Descricao |
|---|---|---|
width | string | Largura uniforme dos lados (ex. "1pt", "0.5mm") |
widths | array de 4 strings | Larguras por lado [top, right, bottom, left] (vence sobre width) |
color | string | Cor da borda ("#RRGGBB", nomeado ou "gray(0.5)") |
style | string | "solid" (padrao), "dashed", "dotted", "none" |
Objeto List
{"type": "list", "list": {"items": ["Item 1", "Item 2", "Item 3"]}}
{"type": "list", "list": {"type": "ordered", "items": ["First", "Second", "Third"]}}
Objeto QR Code
{"span": 6, "qrcode": {"data": "https://gpdf.dev", "size": "25mm", "minSize": "20mm"}}
Since v1.0.6 Com minSize, o QR code transborda para a proxima pagina em vez de encolher abaixo do valor informado quando o espaco restante e insuficiente.
Objeto Barcode
{"span": 6, "barcode": {"data": "INV-001", "format": "code128"}}
Posicionamento Absoluto
Posicione elementos em coordenadas XY exatas, fora do fluxo normal do grid:
{
"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"}
]
}
]
}
O array absolute pode aparecer no nivel superior (aplica-se a todas as paginas) ou dentro de definicoes de paginas individuais.
| Campo | Tipo | Obrigatorio | Descricao |
|---|---|---|---|
x | string | Sim | Coordenada X (string de dimensao) |
y | string | Sim | Coordenada Y (string de dimensao) |
width | string | Nao | Largura explicita (padrao: espaco restante) |
height | string | Nao | Altura explicita (padrao: espaco restante) |
origin | string | Nao | "content" (padrao) ou "page" |
elements | array | Sim | Array de objetos de elementos |
Strings de Dimensao
| Formato | Exemplo |
|---|---|
| Milimetros | "20mm" |
| Pontos | "12pt" |
| Centimetros | "2.5cm" |
| Polegadas | "1in" |
Cores Nomeadas
JSON schemas suportam cores nomeadas: "red", "green", "blue", "yellow", "cyan", "magenta", "black", "white", "gray".
Ou use o formato hexadecimal: "#FF6B6B", "#1A237E".
Combinando com Opcoes Go
Sobrescreva ou estenda JSON schemas com opcoes Go:
fontData, _ := os.ReadFile("fonts/NotoSansJP-Regular.ttf")
doc, err := template.FromJSON(schema, data,
template.WithFont("NotoSansJP", fontData),
template.WithDefaultFont("NotoSansJP", 12),
)