Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool

Input Sanitization Best Practices for JSON Formatters

If your JSON formatter accepts pasted API responses, uploaded files, or any other untrusted payload, the goal is not to "clean up" JSON until it parses. The goal is to reject malformed input, control resource usage, protect secrets, and render valid data without turning user content into executable HTML or JavaScript.

For JSON formatters, sanitization usually means four separate things: strict validation, structural limits, safe output encoding, and optional redaction. Keeping those concerns separate leads to safer tools and fewer confusing edge cases.

What a Search User Usually Needs

A useful JSON formatter guide should answer these questions directly:

  • How do I validate JSON safely? Parse strictly and fail closed instead of repairing input with regexes.
  • How do I prevent XSS in a web formatter? Treat formatted JSON as text unless you have a fully escaped token renderer.
  • How do I stop large payloads from freezing the browser? Enforce byte, depth, and node limits before pretty-printing.
  • What about secrets and duplicate keys? Redact sensitive values and decide whether duplicate object keys are warnings or hard failures.

The Practical Workflow

A robust JSON formatter pipeline is simple: accept raw text, parse it strictly, inspect the parsed structure, optionally redact, then render the result through a safe sink.

1. Parse Strictly and Fail Closed

Start with a real JSON parser, not string replacement. If the payload contains comments, trailing commas, or invalid quotes, reject it or label the mode clearly as non-standard JSON. Quietly auto-fixing malformed input can hide upstream bugs and create interoperability problems later.

Strict parse with a byte limit:

function parseJsonInput(input: string, maxBytes = 1_000_000) {
  const bytes = new TextEncoder().encode(input).length;
  if (bytes > maxBytes) {
    throw new Error("Input is too large to format safely.");
  }

  try {
    return JSON.parse(input);
  } catch {
    throw new Error("Input is not valid JSON.");
  }
}

Do not sanitize JSON by stripping characters until it parses. A formatter should reject invalid JSON unless it explicitly supports a separate lenient mode.

2. Enforce Depth and Node Limits

Valid JSON can still be operationally unsafe. Extremely large arrays, deeply nested objects, and huge string values can lock up the main thread or exhaust memory during formatting and syntax highlighting.

Inspect structure after parsing and stop early when the payload crosses the limits your UI can handle.

Iterative shape inspection:

type JsonValue =
  | null
  | boolean
  | number
  | string
  | JsonValue[]
  | { [key: string]: JsonValue };

function inspectJsonShape(
  root: JsonValue,
  limits = { maxDepth: 40, maxNodes: 50_000 }
) {
  const stack = [{ value: root, depth: 1 }];
  let nodes = 0;

  while (stack.length > 0) {
    const current = stack.pop()!;
    nodes += 1;

    if (nodes > limits.maxNodes) {
      throw new Error("JSON contains too many values to format safely.");
    }

    if (current.depth > limits.maxDepth) {
      throw new Error("JSON nesting is too deep to format safely.");
    }

    if (Array.isArray(current.value)) {
      for (const item of current.value) {
        stack.push({ value: item, depth: current.depth + 1 });
      }
      continue;
    }

    if (current.value && typeof current.value === "object") {
      for (const value of Object.values(current.value)) {
        stack.push({ value, depth: current.depth + 1 });
      }
    }
  }
}

Pick limits based on your UI and hardware budget, then make them explicit in product copy so users know why a payload was rejected.

3. Decide How to Handle Duplicate Keys and Non-standard JSON

Duplicate keys are not a harmless formatting detail. The JSON specification says object member names should be unique, and different parsers can behave differently when they are not. Many implementations keep only the last value, which means a formatter can accidentally hide earlier data.

  • If duplicate keys matter, detect them before data becomes a plain object. Once JSON.parse collapses duplicates, you cannot reliably recover them afterward.
  • Be explicit about comments and trailing commas. Those belong to JSON5-like modes, not standard JSON.
  • Show warnings in the UI. A formatter that silently accepts ambiguous input makes debugging harder.

Rule of thumb:

Strict JSON formatters should reject ambiguous input. Helpful repair modes are fine only when they are clearly labeled and never confused with standards-compliant validation.

4. Render JSON as Text, Not HTML

The biggest security mistake in web-based JSON formatters is treating formatted output as trusted HTML. Strings inside valid JSON can still contain <script>, event handlers, or markup fragments. Parsing JSON safely does not make those strings safe to inject into the DOM as HTML.

Safe React rendering:

function SafeJsonPreview({ input }: { input: string }) {
  const parsed = parseJsonInput(input);
  inspectJsonShape(parsed);
  const formatted = JSON.stringify(parsed, null, 2);

  return <pre className="overflow-x-auto">{formatted}</pre>;
}

// Avoid building highlighted HTML from untrusted JSON and then doing this:
// <pre dangerouslySetInnerHTML={{ __html: highlightedHtml }} />

In React, string children are escaped by default, which is exactly what you want. If you must add syntax highlighting, escape token text before it becomes HTML and keep a strict Content Security Policy. If your formatter exposes an API, return raw JSON with application/json, not text/html.

5. Redact Sensitive Fields Before Display or Logging

Pretty-printing can accidentally expose secrets in screenshots, browser history, error telemetry, and support logs. If your formatter is used for debugging production payloads, add an optional redaction step before display and before any server-side logging.

Simple recursive redaction:

function redactSensitiveFields(
  value: unknown,
  hiddenKeys = ["password", "token", "secret", "authorization", "apiKey"]
): unknown {
  if (Array.isArray(value)) {
    return value.map((item) => redactSensitiveFields(item, hiddenKeys));
  }

  if (!value || typeof value !== "object") {
    return value;
  }

  return Object.fromEntries(
    Object.entries(value).map(([key, child]) => {
      const shouldHide = hiddenKeys.includes(key.toLowerCase());
      return [key, shouldHide ? "[REDACTED]" : redactSensitiveFields(child, hiddenKeys)];
    })
  );
}

Redaction rules should be configurable. A strict allowlist is even better when you know exactly which fields are safe to reveal.

Common Pitfalls

  • Using regex as a parser: Stripping comments, commas, or quotes until input parses creates surprising behavior and can conceal bad upstream data.
  • Assuming `JSON.parse` solves XSS: It validates syntax, but it does not make string content safe for HTML sinks.
  • Ignoring duplicate keys: Ambiguous objects can display one value while another parser keeps a different one.
  • Logging raw user payloads: Parse failures often end up in logs with secrets intact.
  • Formatting huge payloads on the main thread: Even valid JSON can freeze the UI if size and structure limits are missing.

Quick Checklist

  • Parse with a strict JSON parser and fail closed.
  • Set maximum byte size, depth, and node-count limits.
  • Decide whether duplicate keys are warnings or errors.
  • Render formatted JSON as text, not raw HTML.
  • Use a strict CSP if any highlighted HTML is generated.
  • Redact sensitive fields before display, telemetry, and logs.
  • Label any JSON5 or repair mode clearly so users do not confuse it with standard JSON validation.

The best input sanitization strategy for JSON formatters is simple: validate strictly, apply resource limits, keep rendering in safe text contexts, and redact secrets when needed. That gives users a formatter that is genuinely helpful without silently changing their data or creating an avoidable XSS risk.

Need help with your JSON?

Try our JSON Formatter tool to automatically identify and fix syntax errors in your JSON. JSON Formatter tool