How to Convert JSON to PDF with PHP
This PHP tutorial converts JSON into a styled, tagged PDF through the pdfRest Convert to PDF API Tool. The example uploads the payload with structured options and requests a nested hierarchy designed for human reading.
Why Convert JSON to PDF with PHP?
PHP commerce and portal applications generate JSON for orders, fulfillment events, account settings, and background jobs. A raw payload is useful to the application but can create unnecessary friction when customer service or a partner needs a readable record.
An online store might receive a JSON fulfillment response containing packages, tracking events, item arrays, and exception details. PHP can convert the response into a hierarchy-formatted PDF and attach it to an escalated order. Agents can follow the nested information without searching through punctuation or copying values into a separate document.
Source presentation remains available when technical support needs normalized JSON syntax for troubleshooting. One PHP integration can therefore produce either a reader-oriented case attachment or a developer-oriented payload record while keeping common styling and metadata.
PHP Code Example for Converting JSON to PDF
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Utils;
// By default, we use the US-based API service. This is the primary endpoint for global use.
$apiUrl = "https://api.pdfrest.com";
/* For GDPR compliance and enhanced performance for European users, you can switch to the EU-based service by uncommenting the URL below.
* For more information visit https://pdfrest.com/pricing#how-do-eu-gdpr-api-calls-work
*/
//$apiUrl = "https://eu-api.pdfrest.com";
$inputPath = '/path/to/sample.json';
$options = json_decode('{"title":"Structured Content Sample","language":"en-US","enable_tagging":true,"page_setup":{"size":"Letter","orientation":"portrait","margin":{"top":36,"right":42,"bottom":36,"left":42}},"style":{"font":"Arial","heading_font":"Arial","code_font":"Courier","text_size":11,"text_color_rgb":[34,34,34],"heading_scale":1.35,"table":{"column_width_weights":[2,3,2],"keep_header_with_first_row":true,"repeat_headers_on_overflow":true,"show_borders":true,"border_width":0.75,"border_color_rgb":[180,188,200],"header_fill_color_rgb":[33,64,98],"header_text_color_rgb":[255,255,255],"row_fill_color_rgb":[250,250,252],"alternate_row_fill_color_rgb":[235,240,246],"cell_padding":{"top":6,"right":8,"bottom":6,"left":8}}},"data_presentation":"hierarchy"}', true);
// This sample converts JSON input to a tagged PDF through multipart /pdf.
// It demonstrates structured_text_options and the format-specific conversion options.
$multipart = [
['name' => 'file', 'contents' => Utils::tryFopen($inputPath, 'r'), 'filename' => basename($inputPath)],
['name' => 'structured_text_options', 'contents' => json_encode($options)],
['name' => 'output', 'contents' => 'pdf_from_json'],
];
$response = (new Client())->post($apiUrl . '/pdf', ['headers' => ['Api-Key' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'Accept' => 'application/json'], 'multipart' => $multipart]);
echo $response->getBody();
Source: View the sample on GitHub
Breaking Down the Code
This PHP JSON example relies on Guzzle for HTTP and PSR-7 stream utilities for the upload. When using the code outside this repository, add the client with composer require guzzlehttp/guzzle.
require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Utils;
The PHP endpoint excerpt keeps regional routing explicit for this JSON operation:
// By default, we use the US-based API service. This is the primary endpoint for global use. $apiUrl = "https://api.pdfrest.com"; /* For GDPR compliance and enhanced performance for European users, you can switch to the EU-based service by uncommenting the URL below. * For more information visit https://pdfrest.com/pricing#how-do-eu-gdpr-api-calls-work */ //$apiUrl = "https://eu-api.pdfrest.com";
PHP opens the .json source as a PSR-7 stream and includes its filename in the multipart part. The extension selects JSON processing without duplicating the format in the options JSON.
$inputPath = '/path/to/sample.json';
$options = json_decode('{"title":"Structured Content Sample","language":"en-US","enable_tagging":true,"page_setup":{"size":"Letter","orientation":"portrait","margin":{"top":36,"right":42,"bottom":36,"left":42}},"style":{"font":"Arial","heading_font":"Arial","code_font":"Courier","text_size":11,"text_color_rgb":[34,34,34],"heading_scale":1.35,"table":{"column_width_weights":[2,3,2],"keep_header_with_first_row":true,"repeat_headers_on_overflow":true,"show_borders":true,"border_width":0.75,"border_color_rgb":[180,188,200],"header_fill_color_rgb":[33,64,98],"header_text_color_rgb":[255,255,255],"row_fill_color_rgb":[250,250,252],"alternate_row_fill_color_rgb":[235,240,246],"cell_padding":{"top":6,"right":8,"bottom":6,"left":8}}},"data_presentation":"hierarchy"}', true);
The array decoded into $options is serialized as pdfRest’s structured_text_options. It describes the PDF title and language, explicitly turns on tagging, chooses Letter portrait pages with 36-point margins, and provides typography plus JSON-specific styling.
{
"data_presentation": "hierarchy"
}
source is the default. It validates and parses the input, then pretty-prints normalized JSON syntax in a code-style block; original indentation and insignificant whitespace are not preserved. hierarchy removes the syntax and creates a nested list in which property names are bold and primitive values appear as key-value items.
Scalar arrays become ordinary nested values. Arrays containing objects or other arrays label their members Item 1, Item 2, and so on. The converter preserves JSON structure but intentionally does not infer application-specific report meaning. Malformed JSON is rejected in either presentation mode.
The sample’s shared style.table object does not affect JSON source or hierarchy output. It can be omitted when the profile is used only for JSON conversion.
The PHP multipart array assigns name and contents values to the JSON stream, serialized structured_text_options, and requested output name.
// It demonstrates structured_text_options and the format-specific conversion options. $multipart = [ ['name' => 'file', 'contents' => Utils::tryFopen($inputPath, 'r'), 'filename' => basename($inputPath)], ['name' => 'structured_text_options', 'contents' => json_encode($options)], ['name' => 'output', 'contents' => 'pdf_from_json'], ]; $response = (new Client())->post($apiUrl . '/pdf', ['headers' => ['Api-Key' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'Accept' => 'application/json'], 'multipart' => $multipart]); echo $response->getBody();
Guzzle prepares and submits the JSON multipart body with the API key. The response body contains generated-resource information on success and service error details when the conversion cannot be completed.
['name' => 'file', 'contents' => Utils::tryFopen($inputPath, 'r'), 'filename' => basename($inputPath)], ['name' => 'structured_text_options', 'contents' => json_encode($options)], ['name' => 'output', 'contents' => 'pdf_from_json'], ]; $response = (new Client())->post($apiUrl . '/pdf', ['headers' => ['Api-Key' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'Accept' => 'application/json'], 'multipart' => $multipart]); echo $response->getBody();
Beyond the Tutorial
This method can generate downloadable account snapshots, order-event records, job summaries, and partner-integration evidence. It is especially useful when payload structures vary enough that maintaining a custom template for every response would be impractical.
Tagged structure supports document navigation and later processing but is not an automatic accessibility guarantee. Exercise different JSON shapes in API Lab and consult the Convert to PDF API documentation for the complete set of controls.