Documentation

R4PDF

A free, open-source .NET library that converts JSON templates into fully customizable PDFs. No paid licenses — define your layout in JSON and generate professional documents.

C#.NET 8+NuGetPdfSharpCoreMIT License

Installation#

Install R4PDF from NuGet using your preferred method:

dotnet add package R4PDF
Note
Linux users: R4PDF uses Liberation Sans for rendering. Install via sudo apt install fonts-liberation. Windows and macOS use bundled fonts automatically.

Quick Start#

Create a PdfGenerator instance, define a JSON template, and call Generate(). The generator is safe to instantiate once and reuse across requests.

Program.cs
using R4PDF;

var generator = new PdfGenerator();

var template = """
{
    "pages": [{
        "body": {
            "elements": [
                { "type": "text", "text": "Hello, World!", "fontSize": 24, "fontWeight": "bold" },
                { "type": "paragraph", "content": "Generated from a JSON template." }
            ]
        }
    }]
}
""";

byte[] pdf = generator.Generate(template);
generator.GenerateToFile(template, "output.pdf");
Tip
The JSON parser is lenient — it allows trailing commas and single-line comments (// ...).

Data Binding#

Use ${path.to.value} placeholders in your template and pass a JSON data object as a second argument. Nested dot-notation paths are resolved automatically.

Data Binding
var template = """
{
    "pages": [{
        "body": {
            "elements": [
                { "type": "text", "text": "Hello, ${customer.name}!" },
                { "type": "text", "text": "Order #${order.id}" },
                { "type": "text", "text": "Total: ${order.total}" }
            ]
        }
    }]
}
""";

var data = """
{
    "customer": { "name": "John Doe" },
    "order": { "id": "12345", "total": "$99.95" }
}
""";

byte[] pdf = generator.Generate(template, data);

Resolution Rules

PropertyTypeDescription
StringstringInserted as-is
NumbernumberConverted to text representation
BooleanbooleanBecomes "true" or "false"
NullnullReplaced with empty string
ObjectobjectSerialized as raw JSON text
UnresolvedPlaceholder remains unchanged

Template Schema#

Root Structure

A template has four top-level keys. Only pages is required.

PropertyTypeDescription
metadataobject?PDF document info (title, author, subject, keywords)
settingsobject?Default page settings (size, orientation, margins)
stylesobject?Dictionary of reusable named styles
pagesarrayArray of page definitions (required, min 1)
Full root structure
{
    "metadata": {
        "title": "My Report",
        "author": "Jane Doe",
        "subject": "Quarterly Summary",
        "keywords": "report finance"
    },
    "settings": {
        "pageSize": "A4",
        "orientation": "Portrait",
        "margins": { "top": "20mm", "bottom": "20mm", "left": "15mm", "right": "15mm" }
    },
    "styles": {
        "heading": { "fontSize": 20, "fontWeight": "bold", "color": "#003366" }
    },
    "pages": [ ... ]
}

Page Structure

Each page can override settings and define header, body (required), and footer sections.

PropertyTypeDescription
settingsobject?Per-page overrides for pageSize, orientation, margins
headersection?Header section with height and elements
bodysectionBody section with elements (required)
footersection?Footer section fixed to page bottom

Section Properties

PropertyTypeDescription
heightstring?Section height (e.g., "40mm"). Auto-calculated for body.
backgroundstring?Background color for the section (e.g., "#F5F5F5")
elementsarrayArray of element objects to render
Header + Footer example
{
    "header": {
        "height": "30mm",
        "background": "#F8F9FA",
        "elements": [
            { "type": "text", "text": "Company Report", "fontSize": 12, "color": "#666" }
        ]
    },
    "body": {
        "elements": [{ "type": "text", "text": "Main content", "fontSize": 14 }]
    },
    "footer": {
        "height": "20mm",
        "elements": [
            { "type": "text", "text": "Page {pageNumber} of {pageCount}", "alignment": "center", "fontSize": 9 }
        ]
    }
}

Element Types#

R4PDF supports 6 element types. All share a base set of properties — the type field determines which renderer is used.

Base Element Properties

PropertyTypeDescription
typestring"text" | "paragraph" | "table" | "image" | "line" | "rectangle"
stylestring?Name of a reusable style from the styles dictionary
inlineStyleobject?Inline PdfStyle object for element-level overrides
xstring?Absolute X position (e.g., "10mm")
ystring?Absolute Y position (e.g., "20mm")
widthstring?Element width (e.g., "100mm", "50%")
heightstring?Element height (e.g., "30mm")

text

Single-line text with alignment and font properties.

PropertyTypeDescription
textstringThe text content to display
fontSizenumber?Font size in points (default: 12)
fontWeightstring?"normal" or "bold"
fontFamilystring?Font name (default: "Liberation Sans")
colorstring?Text color (default: "#000000")
alignmentstring?"left", "center", or "right"
{ "type": "text", "text": "Hello World", "fontSize": 14, "fontWeight": "bold", "color": "#003366" }

paragraph

Multi-line text with automatic word wrapping, line height, and spacing control.

PropertyTypeDescription
contentstringThe paragraph text (wraps automatically)
fontSizenumber?Font size in points (default: 12)
fontWeightstring?"normal" or "bold"
colorstring?Text color
alignmentstring?"left", "center", "right", or "justify"
lineHeightnumber?Line spacing multiplier (default: 1.2)
spacing.beforestring?Space before (e.g., "6pt")
spacing.afterstring?Space after (e.g., "6pt")
{
    "type": "paragraph",
    "content": "Long text that will wrap automatically across multiple lines...",
    "fontSize": 11,
    "lineHeight": 1.5,
    "alignment": "justify",
    "spacing": { "before": "6pt", "after": "6pt" }
}

table

Data tables with configurable columns, header styling, alternate row colors, per-row overrides, and borders.

PropertyTypeDescription
columnsarrayColumn definitions with name, width, alignment
rowsarrayRow data: { cells, backgroundColor?, textColor? }
headerStyleobject?PdfStyle for the header row
showHeaderboolean?Show/hide header row (default: true)
alternateRowColorsboolean?Enable alternate row coloring
alternateColorstring?Alternate row color (e.g., "#F5F5F5")
bordersobject?Border config: { width, color }

Column widths support three modes:

PropertyTypeDescription
Percentage"50%"Percentage of available table width
Fixed"100mm"Fixed width in any unit
Auto(omitted)Equally divided remaining space
{
    "type": "table",
    "columns": [
        { "name": "Item",  "width": "50%" },
        { "name": "Price", "width": "25%", "alignment": "right" },
        { "name": "Qty",   "width": "25%", "alignment": "center" }
    ],
    "rows": [
        { "cells": ["Widget A", "$10.00", "3"] },
        { "cells": ["Widget B", "$5.50",  "7"], "backgroundColor": "#FFF3CD", "textColor": "#856404" }
    ],
    "headerStyle": { "backgroundColor": "#003366", "color": "#FFFFFF", "fontWeight": "bold" },
    "alternateRowColors": true,
    "alternateColor": "#F5F5F5",
    "borders": { "width": "0.5pt", "color": "#CCCCCC" }
}

image

Embed images via base64 data URIs or file paths. Scales to fit width while preserving aspect ratio.

PropertyTypeDescription
sourcestringFile path or data:image/png;base64,... URI
widthstring?Image width (e.g., "50mm")
heightstring?Image height (auto if aspect ratio preserved)
alignmentstring?"left", "center", or "right"
maintainAspectRatioboolean?Preserve aspect ratio (default: true)
{ "type": "image", "source": "data:image/png;base64,iVBOR...", "width": "60mm", "alignment": "center" }

line

Horizontal rule or absolutely positioned line with optional dash patterns.

PropertyTypeDescription
colorstring?Line color (default: black)
strokeWidthstring?Thickness (e.g., "1pt")
dashPatternstring?Dash values (e.g., "4,2")
x1, y1string?Start point (absolute)
x2, y2string?End point (absolute)
// Horizontal rule
{ "type": "line", "color": "#CCCCCC", "strokeWidth": "1pt" }

// Dashed
{ "type": "line", "color": "#003366", "strokeWidth": "2pt", "dashPattern": "6,3" }

// Absolute diagonal
{ "type": "line", "x1": "10mm", "y1": "10mm", "x2": "100mm", "y2": "50mm", "color": "#FF0000" }

rectangle

Filled or stroked rectangle with optional rounded corners.

PropertyTypeDescription
widthstring?Width (default: available width)
heightstring?Height (default: 20pt)
fillColorstring?Interior fill color
strokeColorstring?Border color
strokeWidthstring?Border thickness (e.g., "1pt")
cornerRadiusstring?Rounded corners (e.g., "3mm")
{ "type": "rectangle", "width": "100mm", "height": "50mm", "fillColor": "#EEE", "strokeColor": "#003366", "cornerRadius": "3mm" }

Style System#

R4PDF uses a three-level style resolution. Define reusable styles in a root dictionary, apply them via style, and override with direct properties.

Priority (lowest → highest)

1Named StyleFrom the root styles dictionary
2Inline StylePdfStyle object via inlineStyle
3Direct PropertiesfontSize, color, etc. on the element

Style Properties

PropertyTypeDescription
fontFamilystring?Font name (e.g., "Helvetica")
fontSizenumber?Font size in points
fontWeightstring?"normal" or "bold"
fontStylestring?"normal" or "italic"
colorstring?Text/foreground color
backgroundColorstring?Background fill color
alignmentstring?"left", "center", "right", "justify"
lineHeightnumber?Line spacing multiplier
paddingstring?Universal padding (e.g., "5mm")
borderobject?{ width, color, type }
Defining and using styles
{
    "styles": {
        "heading": { "fontSize": 20, "fontWeight": "bold", "color": "#003366" },
        "body":    { "fontSize": 11, "color": "#333", "lineHeight": 1.5 },
        "caption": { "fontSize": 9,  "color": "#888", "fontStyle": "italic" }
    },
    "pages": [{
        "body": {
            "elements": [
                { "type": "text", "text": "Title", "style": "heading" },
                { "type": "paragraph", "content": "Body text...", "style": "body" },

                // Direct property overrides a named style:
                { "type": "text", "text": "Red Title", "style": "heading", "color": "#CC0000" }
            ]
        }
    }]
}

Color Formats#

All color properties accept multiple formats:

PropertyTypeDescription
#RRGGBBstringStandard hex — "#003366"
#RGBstringShorthand — "#F00" → #FF0000
#RRGGBBAAstringWith alpha — "#003366FF"
NamedstringCSS-style: red, blue, transparent, etc.

Supported Named Colors

blackwhiteredgreenblueyelloworangepurplegraydarkgraylightgraytransparent

Fonts#

R4PDF uses Liberation Sans as the default and maps common aliases automatically. All four variants supported: Regular, Bold, Italic, Bold Italic.

Font Aliases

These names all resolve to Liberation Sans:

Liberation SansHelveticaArialSans-serifVerdanaTahomaSegoe UICalibri
// All produce the same result:
{ "type": "text", "text": "Hello", "fontFamily": "Helvetica" }
{ "type": "text", "text": "Hello", "fontFamily": "Arial" }

// Weight & style:
{ "type": "text", "text": "Bold",   "fontWeight": "bold" }
{ "type": "text", "text": "Italic", "fontStyle": "italic" }

Measurement Units#

All size values accept a number + unit suffix. Bare numbers default to points.

PropertyTypeDescription
mmMillimeters1mm = 2.835pt
cmCentimeters1cm = 28.346pt
inInches1in = 72pt
ptPointsBaseline unit
pxPixels (96 DPI)1px = 0.75pt
Tip
Negative values and decimals are supported: "-5mm", "2.5cm".

Page Sizes & Orientation#

Page Sizes

A3A4A5LetterLegalTabloid

Orientation

PortraitLandscape

Default Margins

PropertyTypeDescription
top"20mm"Top margin
bottom"20mm"Bottom margin
left"15mm"Left margin
right"15mm"Right margin
Per-page overrides
{
    "settings": { "pageSize": "A4", "orientation": "Portrait" },
    "pages": [
        { "body": { "elements": [{ "type": "text", "text": "Portrait A4" }] } },
        {
            "settings": { "pageSize": "A3", "orientation": "Landscape" },
            "body": { "elements": [{ "type": "text", "text": "Landscape A3" }] }
        }
    ]
}

Page Number Placeholders#

Use these tokens in text elements — they are replaced automatically during rendering:

PropertyTypeDescription
{pageNumber}tokenCurrent page number (1-based)
{pageCount}tokenTotal number of pages
Footer with page numbers
"footer": {
    "height": "15mm",
    "elements": [
        { "type": "line", "color": "#CCC", "strokeWidth": "0.5pt" },
        { "type": "text", "text": "Page {pageNumber} of {pageCount}", "alignment": "center", "fontSize": 9 }
    ]
}

API Reference#

All methods live on PdfGenerator. The pipeline: Data Binding → Parsing → Rendering → Output.

PdfGenerator methods
using R4PDF;
var generator = new PdfGenerator();

// ── byte[] ───────────────────────────────────────────────
byte[] pdf = generator.Generate(template);
byte[] pdf = generator.Generate(template, data);

// ── Stream ───────────────────────────────────────────────
generator.GenerateToStream(template, stream);
generator.GenerateToStream(template, data, stream);

// ── File ─────────────────────────────────────────────────
generator.GenerateToFile(template, "output.pdf");
generator.GenerateToFile(template, data, "output.pdf");
Generate()
Returns: byte[]

In-memory PDF. Ideal for API responses.

GenerateToStream()
Returns: void

Write to an existing Stream.

GenerateToFile()
Returns: void

Write to disk. Simplest for batch jobs.

Full Example: Invoice#

A complete invoice demonstrating styles, headers/footers, data binding, tables, and page numbers:

invoice-template.json
{
    "metadata": { "title": "Invoice #2024-001", "author": "Acme Corp" },
    "settings": {
        "pageSize": "A4",
        "margins": { "top": "20mm", "bottom": "20mm", "left": "15mm", "right": "15mm" }
    },
    "styles": {
        "title":    { "fontSize": 24, "fontWeight": "bold", "color": "#003366" },
        "subtitle": { "fontSize": 14, "color": "#666" },
        "label":    { "fontSize": 10, "fontWeight": "bold", "color": "#333" },
        "value":    { "fontSize": 10, "color": "#000" },
        "footer":   { "fontSize": 9,  "color": "#999", "alignment": "center" }
    },
    "pages": [{
        "header": {
            "height": "40mm",
            "elements": [
                { "type": "text", "text": "ACME CORPORATION", "style": "title" },
                { "type": "text", "text": "123 Business Ave, New York, NY", "style": "subtitle" },
                { "type": "line", "color": "#003366", "strokeWidth": "2pt" }
            ]
        },
        "body": {
            "elements": [
                { "type": "text", "text": "INVOICE", "fontSize": 20, "fontWeight": "bold", "color": "#003366" },
                { "type": "text", "text": "Invoice #: ${invoice.number}", "style": "value" },
                { "type": "text", "text": "Date: ${invoice.date}", "style": "value" },
                { "type": "text", "text": "" },
                { "type": "text", "text": "Bill To:", "style": "label" },
                { "type": "text", "text": "${customer.name}", "style": "value" },
                { "type": "text", "text": "" },
                {
                    "type": "table",
                    "columns": [
                        { "name": "Description", "width": "45%" },
                        { "name": "Qty",  "width": "15%", "alignment": "center" },
                        { "name": "Price","width": "20%", "alignment": "right" },
                        { "name": "Total","width": "20%", "alignment": "right" }
                    ],
                    "rows": [
                        { "cells": ["Web Development", "40", "$150", "$6,000"] },
                        { "cells": ["UI/UX Design",    "20", "$120", "$2,400"] },
                        { "cells": ["Project Mgmt",    "10", "$100", "$1,000"] }
                    ],
                    "headerStyle": { "backgroundColor": "#003366", "color": "#FFF", "fontWeight": "bold" },
                    "alternateRowColors": true,
                    "alternateColor": "#F0F4F8"
                },
                { "type": "line", "color": "#CCC", "strokeWidth": "0.5pt" },
                { "type": "text", "text": "Total: $9,400.00", "fontSize": 14, "fontWeight": "bold", "alignment": "right", "color": "#003366" }
            ]
        },
        "footer": {
            "height": "20mm",
            "elements": [
                { "type": "line", "color": "#CCC", "strokeWidth": "0.5pt" },
                { "type": "text", "text": "Thank you for your business!", "style": "footer" },
                { "type": "text", "text": "Page {pageNumber} of {pageCount}", "style": "footer" }
            ]
        }
    }]
}
Generate with data
using R4PDF;

var generator = new PdfGenerator();
var template = File.ReadAllText("invoice-template.json");
var data = """
{
    "invoice": { "number": "2024-001", "date": "2024-12-01" },
    "customer": { "name": "John Doe" }
}
""";

generator.GenerateToFile(template, data, "invoice.pdf");

Error Handling#

R4PDF wraps internal errors in PdfGenerationException:

PropertyTypeDescription
Invalid JSONJsonExceptionTemplate fails JSON validation
No pagesJsonExceptionTemplate has zero pages
Missing fontFileNotFoundExceptionLiberation Sans not installed
Missing imageFileNotFoundExceptionImage path doesn't exist
Invalid unitFormatExceptionUnrecognized format (e.g., "20xyz")
Invalid colorFormatExceptionUnrecognized color (e.g., "#ZZZ")
Error handling
using R4PDF;
using R4PDF.Exceptions;

try
{
    var generator = new PdfGenerator();
    byte[] pdf = generator.Generate(template, data);
}
catch (PdfGenerationException ex)
{
    Console.WriteLine($"PDF generation failed: {ex.Message}");
    // ex.InnerException contains the original error
}
Warning
Always wrap generation in a try-catch when processing user-provided templates. Malformed JSON or invalid property values will throw.
R4PDF v1.0.3 — MIT License