How to Convert a PDF Table Into a JSON Array

Convert a PDF table into a JSON array. Define a schema, preserve data types, process scanned PDFs with OCR, and validate the result.

PdfParse Team

A PDF table shows data in rows and columns. An application usually needs records and fields. A JSON array gives one object for each table row.

This guide shows how to convert an invoice table into a JSON array. You will define the schema first. You will then extract and validate the data.

The result that you must get

The source table contains two invoice records:

InvoiceDateVendorPaidAmount
INV-104230 Jun 2026Northwind Office SupplyYes$297.00
INV-104807 Jul 2026Contoso ShippingNo$84.50

The JSON output must contain two objects:

[  {    "invoice_number": "INV-1042",    "invoice_date": "2026-06-30",    "vendor": "Northwind Office Supply",    "paid": true,    "amount": 297.0,    "currency": "USD"  },  {    "invoice_number": "INV-1048",    "invoice_date": "2026-07-07",    "vendor": "Contoso Shipping",    "paid": false,    "amount": 84.5,    "currency": "USD"  }]

Each JSON object is one source row. Each key has one stable meaning.

1. Define one object

First, decide what one JSON object represents.

In this example, one object represents one invoice row. Do not mix table-level information with row-level information without a clear structure.

If the PDF has a report title and a table, use an object with metadata and records:

{  "report_name": "Open invoices",  "report_date": "2026-07-10",  "records": [    {      "invoice_number": "INV-1042",      "amount": 297.0    }  ]}

Use this structure when the report values apply to all rows.

2. Define the schema

Use a stable key and type for each field.

{  "invoice_number": "string",  "invoice_date": "date",  "vendor": "string",  "paid": "boolean",  "amount": "number",  "currency": "string"}

Use these rules:

  • Use snake_case for all keys.
  • Use one key for each concept.
  • Store numbers as numbers.
  • Store true or false values as booleans.
  • Store dates in YYYY-MM-DD format.
  • Store missing values as null when the schema permits it.

Do not put a currency symbol in the amount value. Put the currency code in a separate field.

Incorrect:

{ "amount": "$297.00" }

Correct:

{ "amount": 297.0, "currency": "USD" }

3. Identify digital and scanned PDFs

Try to select one word in the source table.

If you can select the word, the PDF is usually digital. If you cannot select it, the page is probably an image. Use OCR for an image-only page.

For scanned PDFs, check punctuation and small characters. OCR can change a decimal point, a date separator, or a letter in an invoice code.

Do not use OCR output without a value check.

4. Convert the table

Open the PDF to JSON converter. Then do these steps:

  1. Upload the PDF.
  2. Define the JSON fields.
  3. Set the type for each field.
  4. Mark the table rows as repeating records.
  5. Start the extraction.
  6. Compare the output with the source table.
  7. Download the JSON file.

Start with one difficult PDF. Correct the schema before you process the complete file set.

5. Handle wrapped cells and page headers

A PDF can put one cell on two visual lines. Keep the text in one JSON value.

Source:

Northwind OfficeSupply

Output:

{ "vendor": "Northwind Office Supply" }

Do not create two objects for one wrapped row.

Multi-page tables often repeat the header on each page. Exclude repeated headers from the array. Also exclude page numbers, report titles, and subtotal labels unless the schema needs them.

6. Use nested arrays only for nested records

Some table rows contain repeating values. For example, an invoice can have many line items.

Use a nested array for those records:

{  "invoice_number": "INV-1042",  "vendor": "Northwind Office Supply",  "items": [    {      "description": "Ergonomic keyboard",      "quantity": 1,      "unit_price": 95.0    },    {      "description": "Monitor arm",      "quantity": 3,      "unit_price": 60.0    }  ]}

Do not store this data as one comma-separated string. A string removes the record boundaries and data types.

Use a child table instead when you must query, join, or aggregate line items across many documents. The PDF to SQLite converter supports that relational workflow.

7. Validate the JSON

First, confirm that a JSON parser can read the file.

import { readFile } from "node:fs/promises";const text = await readFile("invoices.json", "utf8");const records = JSON.parse(text);if (!Array.isArray(records)) {  throw new Error("The root value must be an array.");}

Then check each record:

for (const [index, record] of records.entries()) {  if (typeof record.invoice_number !== "string") {    throw new Error(`Record ${index}: invoice_number must be a string.`);  }  if (typeof record.amount !== "number") {    throw new Error(`Record ${index}: amount must be a number.`);  }  if (typeof record.paid !== "boolean") {    throw new Error(`Record ${index}: paid must be a boolean.`);  }}

Also compare the JSON with the source PDF:

  • Count the source rows.
  • Count the JSON objects.
  • Check the first and last record.
  • Check the largest and smallest number.
  • Check blank values.
  • Check wrapped cells.
  • Check records at each page break.

Valid JSON syntax does not prove that the values are correct. You must do both checks.

8. Know the limits

Review these inputs carefully:

  • low-resolution scans
  • handwriting
  • rotated pages
  • merged cells
  • tables without clear columns
  • nested tables
  • password-protected PDFs
  • values that use regional number formats

For example, 1,234.56 and 1.234,56 use different separator rules. Define the expected format before you change the value to a JSON number.

Use JSON for application data

JSON is a good output for APIs, automation, and application code. Use CSV for a flat spreadsheet. Use SQLite for related tables and SQL queries.

To start, open the PDF to JSON converter. You can also review the PDF document parser, the API documentation, and pricing.