Back to blog
Test Automation#json#json-formatter#json-validator#qa-tools#api-testing#test-automation

JSON Formatter and Validator: A Practical Guide for QA Engineers

Learn how to format, validate, and troubleshoot JSON in your QA workflow. Covers common JSON errors, how to read validation messages, and why a browser-based JSON formatter is faster than your IDE for day-to-day test debugging.

InnovateBits7 min read

JSON is the lingua franca of modern APIs. Every REST endpoint returns it, every test fixture stores it, and every CI log is full of it. Yet QA engineers spend a surprising amount of time fighting with malformed JSON — a missing comma, an extra brace, a trailing comma that one parser accepts and another rejects.

This guide explains how JSON validation actually works, walks through the most common errors you'll encounter in test automation, and shows how a dedicated JSON formatter fits into your day-to-day QA workflow.


What a JSON formatter actually does

At its core, a JSON formatter does two things:

Parsing — it attempts to deserialise the raw string into a data structure. If parsing fails, the formatter reports an error with the position in the string where the problem occurred.

Serialising — it converts the parsed structure back into a string, this time applying consistent indentation, sorting (optionally), and whitespace.

The key insight is that formatting and validation are the same operation. You cannot format invalid JSON because you cannot parse it first. So any tool that successfully formats your input has also validated it.


The most common JSON errors in QA work

1. Trailing commas

JavaScript allows trailing commas in arrays and objects. JSON does not.

// Invalid JSON — trailing comma after last property
{
  "name": "Alice",
  "role": "QA Engineer",
}

This is by far the most common error when manually editing test fixture files. Many developers write JavaScript all day and reflexively add trailing commas. The fix is to remove the comma after the last element.

2. Single quotes instead of double quotes

JSON strings must use double quotes. Single quotes are invalid.

// Invalid
{'name': 'Alice'}
 
// Valid
{"name": "Alice"}

This trips up engineers who copy values from terminal output or Python REPL sessions, where single-quoted strings are common.

3. Unquoted keys

Unlike JavaScript object literals, JSON requires all keys to be quoted strings.

// Invalid — keys must be quoted
{name: "Alice", role: "QA"}
 
// Valid
{"name": "Alice", "role": "QA"}

4. Comments

JSON does not support comments. This surprises many people because several JSON supersets (JSON5, JSONC) do allow them, and VS Code's settings.json uses JSONC.

// This will fail to parse — comments are not valid JSON
{
  // User details
  "name": "Alice"
}

If you need comments in configuration files, use YAML or TOML instead.

5. Numbers as strings (and vice versa)

A common API contract violation: an endpoint that previously returned "count": 42 starts returning "count": "42". Both are valid JSON, but a test asserting strict equality will fail.

// These are different types — "42" is a string, 42 is a number
{"count": "42"}
{"count": 42}

Your JSON formatter won't flag this as an error, but your type-aware validator (like a JSON Schema validator) will.


Reading validation error messages

When a formatter reports an error, it typically gives you a position. Learning to read these positions quickly saves significant debugging time.

A typical error looks like:

SyntaxError: Expected ',' or '}' after property value in JSON at position 47

Position 47 means character 47 in the raw string (zero-indexed). In a large JSON response this isn't directly useful, which is why good formatters translate the character position into a line and column number:

Line 3, Column 12: Unexpected token '

Workflow tip: When you get a parse error on a large JSON blob, paste it into a formatter immediately. The formatter will highlight the problematic line and column, which is almost always faster than reading the raw string character by character.


JSON formatting in test automation

Test fixtures

Test fixtures (the static JSON files your tests load as input data) need to be consistently formatted for two reasons:

  1. Diff readability — a properly formatted fixture produces readable git diffs. Minified fixtures produce single-line diffs that are impossible to review.
  2. Merge conflict resolution — when two engineers edit the same fixture, formatted JSON produces granular, resolvable conflicts. Minified JSON produces unsolvable conflicts.

Establish a project convention: always store fixtures formatted with 2-space indentation.

# Format all fixture files in place using Node.js
node -e "
  const fs = require('fs');
  const path = require('path');
  const dir = './tests/fixtures';
  fs.readdirSync(dir).filter(f => f.endsWith('.json')).forEach(f => {
    const p = path.join(dir, f);
    const formatted = JSON.stringify(JSON.parse(fs.readFileSync(p, 'utf8')), null, 2);
    fs.writeFileSync(p, formatted + '\n');
  });
"

API response assertions

When asserting on API response bodies in Playwright or Jest, always parse the response before asserting — never do string comparison on JSON:

// Bad — fragile, order-dependent, whitespace-sensitive
expect(responseBody).toBe('{"name":"Alice","role":"QA"}')
 
// Good — structural comparison, order-independent
const body = await response.json()
expect(body.name).toBe('Alice')
expect(body.role).toBe('QA')
 
// Also good — partial match
expect(body).toMatchObject({ name: 'Alice' })

Logging formatted JSON in test output

When a test fails on an API assertion, the error message is much more useful if it shows formatted JSON:

async function assertApiResponse(response: APIResponse) {
  const body = await response.json()
  if (response.status() !== 200) {
    console.error('Response body:', JSON.stringify(body, null, 2))
  }
  expect(response.status()).toBe(200)
}

Minification: when to use it

Minified JSON removes all whitespace, producing the smallest possible string. This matters in two scenarios:

Network payloads — production API responses are typically minified to reduce bandwidth. If you're writing a performance test that measures payload size, compare against the minified byte count.

Environment variables — some CI systems (GitHub Actions, Netlify) store secrets as environment variables with character limits. If you need to store a JSON credentials object, minify it first.

# Minify a JSON file from the command line
node -e "console.log(JSON.stringify(JSON.parse(require('fs').readFileSync('creds.json', 'utf8'))))"

Using the InnovateBits JSON Formatter

The JSON Formatter tool on this site runs entirely in your browser — nothing is sent to a server. Paste your JSON, click Format, and get:

  • Formatted output with configurable indent (2 or 4 spaces)
  • Exact error messages with position information for invalid input
  • One-click copy and download

It's particularly useful for quickly inspecting API responses you've copied from Postman, browser DevTools, or test logs without spinning up a new browser tab or installing a VS Code extension.


JSON Schema validation: the next level

Basic JSON validation confirms that a string is syntactically valid JSON. JSON Schema validation confirms that the structure and types match a defined contract — much more useful for API testing.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["id", "name", "email"],
  "properties": {
    "id":    { "type": "integer" },
    "name":  { "type": "string", "minLength": 1 },
    "email": { "type": "string", "format": "email" }
  },
  "additionalProperties": false
}

Libraries like ajv (JavaScript) and jsonschema (Python) let you validate API responses against a schema in your tests, catching contract violations automatically before they reach production.


Quick reference: JSON rules

RuleValidInvalid
String delimiters"double"'single'
Trailing commasNot allowed{"a":1,}
KeysMust be quoted strings{name: "x"}
CommentsNot supported// comment
NumbersInteger, float, scientific0x1F (hex)
Special valuestrue, false, nullundefined, NaN
Root typeAny value

JSON is simple by design. Its strict rules make it fast to parse and unambiguous — which is exactly what you want in a data exchange format used by hundreds of different languages and runtimes.

Free newsletter

Stay ahead in AI-driven QA

Get practical tutorials on test automation, AI testing, and quality engineering — straight to your inbox. No spam, unsubscribe any time.