# JSON Formatter & Validator: Pretty Print, Minify, Fix, Convert (`data-done-right/json-formatter-validator`) Actor

JSON formatter and validator: pretty print, minify, validate with exact line and column, repair broken JSON (trailing commas, single quotes, comments), convert JSON to CSV, YAML or JSONL, check against JSON Schema. Bulk, no API key.

- **URL**: https://apify.com/data-done-right/json-formatter-validator.md
- **Developed by:** [Data Done Right](https://apify.com/data-done-right) (community)
- **Categories:** Developer tools, Automation, Other
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.28 / 1,000 json processeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## JSON Formatter & Validator: Pretty Print, Minify, Fix, Convert

This **JSON formatter and validator** pretty prints, minifies, validates and repairs JSON in bulk, and converts it to CSV, YAML or JSON Lines. Paste JSON texts, give links to JSON files or APIs, or point it at an Apify dataset. Every input gets one result row with the status, the exact **line and column** of any syntax error, a plain-language hint, and the result. No API key, no AI: the same input always gives the same output.

Typical jobs: check a pile of JSON files before an import, **fix broken JSON** from an LLM or a hand-edited config, pretty print an API response, turn a nested API response into a flat CSV, or test documents against a JSON Schema.

### What can this JSON formatter and validator do

- **Validate JSON** with the exact line, column, character position, error message, the offending line with a caret, and a hint such as "Trailing comma: remove the comma before the closing brace". Duplicate keys are reported as warnings; NaN and Infinity are rejected like a strict parser does.
- **JSON Schema validation** (draft 2020-12 or draft-07): every error with its JSON path (`$.items[2].price`), message and failing keyword. Remote `$ref` links are never downloaded.
- **Pretty print JSON (format)** with 1 to 8 spaces or tabs, optional key sorting and optional ASCII-only output.
- **Minify JSON** to the smallest valid form.
- **Fix broken JSON (repair)**: trailing commas, single quotes, smart quotes, unquoted keys, comments (`//`, `/* */`, `#`), Python `None`/`True`/`False`, `undefined`/`NaN`/`Infinity`, missing commas or colons, raw line breaks inside strings, unescaped inner quotes, invalid backslash escapes, markdown code fences, text before or after the JSON, and **truncated JSON** (missing closing brackets and braces). The row lists every kind of fix with its count and first position, so nothing changes silently.
- **JSON to CSV**: nested objects flattened with your delimiter (`address.city`), arrays as one column per element, joined in one cell, or kept as JSON text; a records path for wrapped data (`data.items`); semicolon, tab or pipe delimiters; optional spreadsheet-formula protection.
- **CSV to JSON**: delimiter auto-detection, number and boolean detection, and optional rebuilding of nested objects from flattened column names.
- **JSON to YAML** and **JSON to JSON Lines (JSONL / NDJSON)**. JSONL files can be validated line by line, with the bad lines listed.
- **Stats**: depth, key count, unique keys, value type counts, longest array and size in bytes.
- **Bulk and safe**: up to 5,000 documents per run. A bad document or URL never stops the run; it gets its own row with a status and a reason.
- **Small results inline, big ones as a file**: results up to 20,000 characters (adjustable) are in the row's `result` field. Larger ones are saved to the key-value store and the row has `resultFile.url`, a signed download link that works without an Apify token.

### How to validate JSON

1. Put your JSON in **JSON texts** (one per entry) or links in **URLs**.
2. Set **Operation** to *Validate*. Optionally paste a **JSON Schema**.
3. Run it. `valid` is true or false, `errorLine` and `errorColumn` point at the problem, `hint` says how to fix it, and `schemaErrors` lists schema violations.

### How to fix broken JSON

Set **Operation** to *Repair*. The cleaned, pretty printed JSON is in `result`, and `changes` shows what was fixed. For Format, Minify and the conversions you can turn on **Repair first if the JSON is invalid** to get the same behaviour in one step. If the text is beyond repair the row says `failed` with the reason and is not charged.

### How to pretty print or minify JSON

Choose *Format / pretty print* or *Minify*. Use **Indent**, **Indent with tabs**, **Sort keys alphabetically** and **Escape non-ASCII characters** to control the output.

### How to convert JSON to CSV

Choose *Convert JSON to CSV*. An array of objects gives one CSV row per element; an object gives one row. If your data is wrapped (`{"data": {"items": [...]}}`) set **Records path** to `data.items`. To turn a whole Apify dataset into one CSV, pick the dataset and turn on **Combine the dataset into one array**.

### Input example

```json
{
  "texts": ["{'name': 'Widget', 'tags': ['a', 'b',], 'price': 9.99, 'in_stock': True, 'owner': None,}"],
  "urls": ["https://api.github.com/repos/apify/crawlee"],
  "operation": "repair",
  "indent": 2
}
```

More examples:

- `{"operation": "validate", "jsonSchema": {"type": "object", "required": ["id"]}}` : validate against a schema.
- `{"operation": "to_csv", "recordsPath": "data.items", "arrayMode": "join", "csvDelimiter": "semicolon"}` : API response to a CSV file.
- `{"operation": "format", "inputFormat": "csv"}` : a CSV text or `.csv` link to a JSON array.
- `{"operation": "to_yaml", "sortKeys": true}` : JSON to YAML.
- `{"datasetId": "<dataset id>", "datasetField": "payload", "operation": "minify"}` : minify the JSON text found in a field of every dataset item.

### Output

One dataset row per document:

```json
{
  "index": 1,
  "source": "{'name': 'Widget', 'tags': ['a', 'b',], 'price': 9.99, 'in_st…",
  "sourceType": "text",
  "operation": "repair",
  "status": "repaired",
  "valid": false,
  "repaired": true,
  "inputFormat": "json",
  "error": "Expecting property name enclosed in double quotes",
  "errorLine": 1,
  "errorColumn": 2,
  "hint": "Keys must use double quotes. Replace single quotes with double quotes.",
  "changes": [
    "converted single quotes to double quotes (8x, first at line 1, column 2)",
    "removed trailing commas (2x, first at line 1, column 37)",
    "replaced Python/uppercase True, False, Null with true, false, null (line 1, column 68)",
    "replaced None, undefined, NaN, Infinity with null (line 1, column 83)"
  ],
  "changeCount": 12,
  "schemaValid": null,
  "sizeBytesIn": 88,
  "sizeBytesOut": 110,
  "result": "{\n  \"name\": \"Widget\",\n  \"tags\": [\n    \"a\",\n    \"b\"\n  ],\n  \"price\": 9.99, ...}",
  "resultFile": null
}
```

`status` is `ok`, `repaired`, `invalid` (syntax or schema errors found), `failed` (download or repair failed) or `skipped` (empty input, item limit, spending limit). `valid` always describes the input as you gave it, before any repair. A `SUMMARY` record in the key-value store lists totals.

### How much does it cost

Pay per event: **$0.0016 per document processed** ($1.60 per 1,000), event `json-processed`. You pay for each item that returned its result. With the Validate operation, a document found invalid still counts, because the verdict is the result. Failed downloads, empty inputs, text that could not be repaired, invalid input for Format/Minify/convert and skipped items are free. In *Combine the dataset* mode one event covers 500 dataset items. Use **Max items** to cap a run.

### Limits (honest)

- **Repair is a best guess.** It fixes the common, unambiguous breakage and reports each fix, but it cannot know what you meant when the text is badly damaged (for example an unescaped quote inside a string next to a comma). Check the `changes` list for important data. A truncated document loses its incomplete last key or value.
- **Numbers pass through Python floats.** `1.10` is written as `1.1`, `1E5` as `100000.0`, and numbers with more than about 17 significant digits lose precision. Whole numbers of any size are kept exactly. A number such as `1e999` cannot be written and is reported as an error.
- **Duplicate keys:** the last value wins (a warning is added).
- JSON Lines input is read as an array of its lines; use *to JSONL* to write it back. CSV is read with a header row (or generated column names) and no schema; all-digit values with a leading zero stay text.
- Files: up to 100 MB per URL (default 20 MB). Download only from public http(s) addresses; private network addresses and requests needing a login or API key header are not supported. Results over 2 MB are always written as a file.
- YAML output uses the safe dumper; YAML input is not supported.
- JSON Schema: drafts 2020-12 and 07. `format` keywords (email, date, ...) are annotations only and are not enforced.

### FAQ

**Why does my JSON fail validation?** Run *Validate*. `errorLine`, `errorColumn`, `errorContext` and `hint` point at the first problem. The most common causes are trailing commas, single quotes, unquoted keys, comments and a missing closing bracket.

**Can it fix JSON from ChatGPT or other LLMs?** Yes, that is a typical use. It removes code fences and chatter around the JSON, quotes keys, fixes trailing commas and closes truncated output. It is rule-based, not AI, so it never invents data.

**Does it send my data anywhere?** No. Everything runs inside the Actor. Only the links you list are downloaded.

**Is the repaired result guaranteed to be valid JSON?** Yes. If the repair succeeds the output is written by a standard JSON serializer. If nothing sensible can be recovered the row is `failed` and free.

**How large can the output be?** Small results are inline. Larger ones go to a file with a signed link (usable without a token); the link stays valid as long as the run's key-value store exists.

**Can I process a whole dataset?** Yes. Pick it in *Dataset with JSON*; each item is a document (or use *Dataset field*). Turn on *Combine the dataset* to get one CSV, YAML or JSON array for all items.

### Related tools

- **Excel to JSON - CSV to JSON & XLSX File Reader** to turn spreadsheets into JSON rows before you validate them.
- **Keyword Extractor: Extract Keywords & Keyphrases from Text** for text analysis on the strings inside your JSON.
- **Extract Text from PDF: OCR, PDF to Text & Markdown** to get text out of documents.

# Actor input Schema

## `texts` (type: `array`):

One JSON document per entry (an object, an array or a whole file pasted as text). Broken JSON is welcome: use the Repair operation to fix it. Each entry gets its own result row. Example: {'a': 1,}

## `urls` (type: `array`):

Optional. Public http(s) links to a JSON, JSONL or CSV file or to an API that returns JSON. Each link gets its own result row. Private network addresses are refused. Example: https://api.github.com/repos/apify/crawlee

## `datasetId` (type: `string`):

Optional. Pick an Apify dataset, for example the output of a scraper. By default every item is processed as one JSON document; set the field below to use a text or JSON field of each item instead.

## `datasetField` (type: `string`):

Optional. Field of each dataset item that holds the JSON (a JSON text, an object, an array or a URL). Dotted paths work. Leave empty to use the whole item. Example: payload or response.data.

## `combineDataset` (type: `boolean`):

Turn on to read all dataset items into ONE JSON array and process it as a single document, for example to turn a whole dataset into one CSV file. Charged as one event per 500 items (at least one). Off: every item is its own result.

## `operation` (type: `string`):

What to do with every input. Validate reports the exact line, column, message and a fix hint. Repair fixes common breakage (trailing commas, single quotes, unquoted keys, comments, Python None/True/False, missing or extra brackets) and lists every change. The to_csv, to_yaml and to_jsonl operations convert.

## `inputFormat` (type: `string`):

How to read the input. Auto reads JSON, and detects JSON Lines (one document per line) and CSV links by their file ending or content type. Choose CSV to convert a CSV text or file to JSON (use Format as the operation). A JSONL input is treated as an array of its lines.

## `autoRepair` (type: `boolean`):

For Format, Minify and the conversions: if the JSON is invalid, repair it first instead of reporting an error. Every change is listed in the result row. The Repair operation always does this.

## `indent` (type: `integer`):

Spaces per level for formatted output (Format, Repair). Example: 2.

## `useTabs` (type: `boolean`):

Use one tab per level instead of spaces.

## `sortKeys` (type: `boolean`):

Sort the keys of every object (a stable order for diffs). Also applies to JSONL and YAML output.

## `asciiOnly` (type: `boolean`):

Write characters outside ASCII as \uXXXX escapes (JSON and JSONL output). Off keeps readable UTF-8 text.

## `includeStats` (type: `boolean`):

Add depth, key count, value types and size to each result row. The Validate and Stats operations always include them.

## `jsonSchema` (type: `object`):

Optional. A JSON Schema (draft 2020-12 or draft-07). Every valid document is also checked against it and the row shows schemaValid and the list of schema errors with their paths. Remote $ref links are not downloaded.

## `schemaDraft` (type: `string`):

Which JSON Schema draft to use. Auto reads the $schema keyword and falls back to 2020-12.

## `recordsPath` (type: `string`):

Optional. Dotted path to the array to turn into CSV rows when the data is wrapped in an object. Example: data.items. Empty: the whole document (an array gives one row per element).

## `flattenDelimiter` (type: `string`):

Joins nested keys into column names, and splits them again for CSV to JSON with unflatten. Example: . gives address.city.

## `arrayMode` (type: `string`):

How arrays inside a record are written. Index: tags.0, tags.1 (one column per element). Join: all values of a list of simple values in one cell. JSON: the array as a JSON text in one cell.

## `arrayJoinSeparator` (type: `string`):

Separator between values when Arrays in CSV is set to Join. Example: a semicolon or a comma and a space.

## `flattenMaxDepth` (type: `integer`):

Stop flattening at this depth and keep deeper data as a JSON text in the cell. 0 flattens everything.

## `csvDelimiter` (type: `string`):

Column separator for CSV output.

## `csvHeader` (type: `boolean`):

Write a header row (JSON to CSV) and read the first row as column names (CSV to JSON).

## `csvInputDelimiter` (type: `string`):

Column separator when reading CSV. Auto picks the most common one in the first line.

## `csvInferTypes` (type: `boolean`):

CSV to JSON: write 42 as a number, true as a boolean and empty cells as null. Values with leading zeros (007) stay text. Off keeps every cell as text.

## `csvUnflatten` (type: `boolean`):

CSV to JSON: turn columns such as address.city back into nested objects (and tags.0, tags.1 back into arrays) using the flatten delimiter.

## `csvEscapeFormulas` (type: `boolean`):

JSON to CSV: prefix cells that start with = + - or @ with an apostrophe so Excel and Sheets do not run them. Numbers are left alone.

## `outputMode` (type: `string`):

Auto puts small results inside the result row (field result) and large ones in a file in the key-value store with a download link (field resultFile). Inline always keeps it in the row (up to 2 MB). File always writes a file.

## `inlineMaxChars` (type: `integer`):

In Auto mode, results longer than this are saved as a file. Example: 20000.

## `maxItems` (type: `integer`):

Most documents processed in one run. Extra items are listed as skipped and are not charged. Caps your cost.

## `maxFileSizeMb` (type: `integer`):

Largest JSON file or API response accepted per URL. Example: 20.

## `concurrency` (type: `integer`):

How many items are processed at the same time.

## `timeoutSecs` (type: `integer`):

How long to wait for a URL before giving up on it.

## Actor input object example

```json
{
  "texts": [
    "{'name': 'Widget', 'tags': ['a', 'b',], 'price': 9.99, 'in_stock': True, // note\n 'owner': None,}"
  ],
  "combineDataset": false,
  "operation": "repair",
  "inputFormat": "auto",
  "autoRepair": false,
  "indent": 2,
  "useTabs": false,
  "sortKeys": false,
  "asciiOnly": false,
  "includeStats": false,
  "schemaDraft": "auto",
  "flattenDelimiter": ".",
  "arrayMode": "index",
  "arrayJoinSeparator": ", ",
  "flattenMaxDepth": 0,
  "csvDelimiter": "comma",
  "csvHeader": true,
  "csvInputDelimiter": "auto",
  "csvInferTypes": true,
  "csvUnflatten": false,
  "csvEscapeFormulas": false,
  "outputMode": "auto",
  "inlineMaxChars": 20000,
  "maxItems": 100,
  "maxFileSizeMb": 20,
  "concurrency": 5,
  "timeoutSecs": 30
}
```

# Actor output Schema

## `results` (type: `string`):

All result items of this run (the default dataset), as JSON, CSV, Excel and more.

## `records` (type: `string`):

Key-value store records: the run summary, notes on any problems, and any files.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "texts": [
        "{'name': 'Widget', 'tags': ['a', 'b',], 'price': 9.99, 'in_stock': True, // note\n 'owner': None,}"
    ],
    "operation": "repair"
};

// Run the Actor and wait for it to finish
const run = await client.actor("data-done-right/json-formatter-validator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "texts": ["""{'name': 'Widget', 'tags': ['a', 'b',], 'price': 9.99, 'in_stock': True, // note
 'owner': None,}"""],
    "operation": "repair",
}

# Run the Actor and wait for it to finish
run = client.actor("data-done-right/json-formatter-validator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "texts": [
    "{'\''name'\'': '\''Widget'\'', '\''tags'\'': ['\''a'\'', '\''b'\'',], '\''price'\'': 9.99, '\''in_stock'\'': True, // note\\n '\''owner'\'': None,}"
  ],
  "operation": "repair"
}' |
apify call data-done-right/json-formatter-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data-done-right/json-formatter-validator"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/B01dlmwBTJwRgfxXB/builds/7H1CduOzvEug0rXs4/openapi.json
