Skip to content
Advanced

4 JSON Repair Checks Before Accepting Recovered Data

·10 min read
4 JSON Repair Checks Before Accepting Recovered Data - Advanced guide from JSON Prettifier

Quick answer: Run four JSON repair acceptance checks: confirm the intended source was selected, establish completeness, validate application invariants, and retain review evidence before release. Successful parsing only proves that the candidate has acceptable JSON syntax. It does not recover absent facts, establish the author's intent, or authorize downstream actions.

A repair button turns a broken response green. The file now parses, but the order list may still be incomplete or the wrong example may have been extracted. The risky step is promoting that candidate into trusted processing without checking what the green result actually means.

Use the JSON Fixer to explore sanitized malformed text. It preserves the original input for comparison and reports detected repair categories. The AI-generated JSON fixing guide covers syntax cleanup; this article focuses on the acceptance decision afterward. Wikipedia's data validation overview provides background on that broader distinction.

Recent developer interest makes this concrete: jsonrepair issue 208, opened October 18, 2026, reports unexpected nesting from a doubled comma in version 3.15.0. That report is a specific reproduction, not a universal claim about every repair. The four independent examples below were executed against this repository's fixer helper and installed jsonrepair 3.15.0. Run relative imports from the repository root with its dependencies installed.

1. Did the repair select the source document you actually intended?

Check the relationship between the original input and the selected candidate before validating its fields. A wrapper can contain examples, explanations, or several documents, and an extraction heuristic can choose the wrong one. Bind acceptance to trusted request context and an explicit document-selection policy rather than assuming the first parseable object is authoritative.

Imagine a support response containing a sample order followed by the real order. Both objects have valid identifiers and plausible amounts. A schema can accept either, so schema validation cannot prove which document belongs to the current request. Source selection needs its own evidence, such as a request identifier checked against trusted application context.

The repository wrapper selects the first matching fenced block when one is present. Its repair helper source makes that behavior inspectable. Do not assume that the underlying repair library and the site's surrounding extraction logic have identical document-selection policies.

import assert from 'node:assert/strict';
import { fixJson } from './lib/json-tools/repair.mjs';
const fence = String.fromCharCode(96).repeat(3);
const original = [fence + 'json', '{"requestId":"example"}', fence,
  'Actual result:', fence + 'json', '{"requestId":"live-42"}', fence].join('\n');
const result = fixJson(original);
assert.equal(result.valid, true);
const candidate = JSON.parse(result.fixed);
assert.equal(candidate.requestId, 'example');
assert.notEqual(candidate.requestId, 'live-42');

This is a successful extraction test and an intentionally unacceptable candidate for the live request. It demonstrates why a parse-success flag cannot serve as the entire acceptance condition. Keep a negative fixture where an attractive but unrelated document appears before the expected result.

Prefer a protocol that delivers one explicitly identified payload. If several documents are legitimate, define how they are separated and selected before repairing any of them. Avoid a rule that searches until it finds an object satisfying loose requirements; an unrelated example can satisfy the same requirements by coincidence.

Do not trust a request identifier solely because it appears inside the repaired object. Compare it with the request your application actually issued and, where available, an independently authenticated response envelope. If the sender can choose both the identifier and the values being accepted, matching those fields to each other establishes consistency, not origin. Keep that distinction visible in the acceptance policy.

Retain the original wrapper during diagnosis, subject to privacy controls. Copying only the repaired object into a bug report removes the context needed to explain a selection error. Conversely, do not upload private production material simply to reproduce a heuristic. Replace identifiers and sensitive values consistently while preserving the structure that caused the selection.

2. Is the recovered candidate complete rather than merely closed?

Verify completeness using evidence independent of the repaired text, such as a trusted record count, expected identifier set, or source completion signal. Adding closing punctuation can produce a valid prefix while missing records remain absent. If completion cannot be established, quarantine the candidate or request a fresh authoritative response instead of inferring missing facts.

Truncation is especially deceptive because the resulting prefix often looks reasonable. A two-item list is a valid list even when the source promised three items. The final visible string may also be only part of a customer name or code. A repair algorithm can close its quote without knowing the rest of that value.

The jsonrepair maintainer documentation lists truncated-input repair among its supported transformations. That describes a syntax capability, not an ability to reconstruct facts never received. Our unexpected end of JSON guide explains common causes of incomplete input before repair is considered.

import assert from 'node:assert/strict';
import { fixJson } from './lib/json-tools/repair.mjs';
const original = '{"items":[{"id":"A"},{"id":"B"},';
const result = fixJson(original);
assert.equal(result.valid, true);
const candidate = JSON.parse(result.fixed);
assert.equal(candidate.items.length, 2);
const trustedExpectedIds = ['A', 'B', 'C'];
assert.notDeepEqual(candidate.items.map(item => item.id), trustedExpectedIds);

The expected identifiers in this fixture stand for independently trusted application context. A count or completion flag copied from the same damaged response is weaker evidence and needs its own trust analysis. Do not manufacture an expected count from the repaired array length, because that makes the test tautological.

For streamed responses, wait for the protocol's supported completion condition before attempting final acceptance. A fragment may be incomplete simply because more data is still arriving. The streaming JSON guide addresses that separate transport boundary. Recovery after a terminated stream is not equivalent to interpreting a still-active stream.

Check duplicate identifiers as well as missing ones. Matching a total count does not prove the intended records were recovered if one record appears twice and another is absent. For partial recovery workflows, label the result as partial and define which read-only uses are permitted. Do not silently feed a partial list into a process that interprets absence as deletion or cancellation.

When fetching a replacement response, keep the attempts separate. Combining a recovered prefix from one attempt with a suffix from another can mix different snapshots even if the final object parses. Reconcile records under a documented snapshot or version rule, or accept a complete replacement. Preserve enough request context to explain which attempt supplied the candidate that was ultimately reviewed.

3. Do the repaired values satisfy application invariants without guesswork?

Validate the candidate's types, required fields, allowed values, and cross-field relationships after parsing. Repairs can translate non-JSON literals or infer structure without proving business meaning. Reject unexplained changes to identifiers, amounts, or container shape, and use authoritative context when a decision depends on facts that syntax and schema checks cannot establish.

Separate three outcomes in your application: repair failed, parsing succeeded but validation failed, and the candidate passed the configured acceptance checks. Collapsing them into an empty object hides failures and can accidentally activate defaults. A failed amount or identifier check should remain visible to the caller that decides whether to retry or quarantine.

The JSON Schema object reference documents required properties and controls for additional properties. Use a real schema validator for the schema vocabulary your application adopts. The following small assertions demonstrate only an illustrative contract, not a full JSON Schema implementation.

import assert from 'node:assert/strict';
import { fixJson } from './lib/json-tools/repair.mjs';
const acceptExample = original => {
  const result = fixJson(original);
  assert.equal(result.valid, true);
  const value = JSON.parse(result.fixed);
  assert.equal(typeof value.accountCode, 'string');
  assert.match(value.accountCode, /^\d{5}$/);
  assert.equal(typeof value.active, 'boolean');
  assert(Number.isSafeInteger(value.quantity) && value.quantity >= 0);
  return value;
};
assert.equal(acceptExample("{accountCode:'00123',active:True,quantity:2}")
  .accountCode, '00123');
assert.throws(() => acceptExample('{accountCode:123,active:true,quantity:2}'));

The accepted literal translation does not prove that the sender intended an active account. It only satisfies the stated test. If authorization or eligibility depends on that flag, check it against the application's trusted state rather than believing a repaired field. Parsing data must not grant it permission to change the system.

Keep fixtures for container boundaries too. The recent doubled-comma report illustrates a shape concern, while your own library version and wrapper may reject or transform similar input differently. Pin the version and assert the actual result. Do not flatten a surprising nested array merely to satisfy a downstream loop without establishing what the source meant.

Run validation before applying convenience defaults or coercions, unless those transformations are explicitly part of the acceptance contract. Otherwise, a missing quantity might become zero and an invalid candidate might appear valid only because the evidence of damage was replaced. Record which transformations were permitted, then test their output independently from the repair step so failures can be attributed to the correct boundary.

For precision-sensitive values, review the JSON number precision guide. Preserve identifiers as strings where the contract requires them; converting a rounded number back to text cannot restore lost digits. When evidence supports several plausible values, the correct outcome is a rejected candidate or a fresh source, not a more elaborate heuristic.

4. Is there review evidence before the candidate enters trusted processing?

Keep the original and candidate separate, record the repair implementation and validation outcome, and require the workflow's acceptance decision before promotion. Detected-category notes are useful diagnostics, not a complete edit log or proof of intent. Preserve enough evidence to reproduce the decision while applying appropriate privacy, retention, and access controls to source material.

For a one-off support task, review can be a person checking a sanitized copy against an authoritative record. For a production pipeline, it may be an explicit policy that permits only a narrow class of transformations and quarantines everything else. The important property is that repair does not silently bypass the acceptance boundary.

import assert from 'node:assert/strict';
import { createHash } from 'node:crypto';
import { fixJson } from './lib/json-tools/repair.mjs';
const original = '{"quantity":2,}';
const result = fixJson(original);
assert.equal(result.valid, true);
const digest = text => createHash('sha256').update(text).digest('hex');
const evidence = { originalDigest: digest(original),
  candidateDigest: digest(result.fixed), reviewed: false };
assert.notEqual(evidence.originalDigest, evidence.candidateDigest);
const promoteExample = record => {
  assert.equal(record.reviewed, true);
  return JSON.parse(result.fixed);
};
assert.throws(() => promoteExample(evidence));
evidence.reviewed = true;
assert.deepEqual(promoteExample(evidence), { quantity: 2 });

This is a local illustration of a gate, not an authentication system or durable audit store. Anyone who can change the example boolean can pass it. In a real workflow, bind review to the exact candidate and protect who can approve it; do not reuse approval after the payload changes.

Likewise, a digest identifies bytes for comparison but does not prove origin or correctness. It cannot replace retained evidence when reproduction is required, and hashing sensitive low-entropy values does not automatically anonymize them. Decide which artifacts can be stored, who may read them, and when they must expire.

On a library upgrade, replay a sanitized corpus of accepted and rejected cases before changing production behavior. Compare both the repaired text and the acceptance outcome. A different candidate can be legitimate, but it deserves review rather than automatic inheritance of an earlier approval. Keep the wrapper version with the library version because extraction and preprocessing can change the result before repair begins.

Use a text comparison for malformed source versus candidate. The JSON comparison tool is useful when comparing two valid parsed documents, such as an authoritative baseline and an accepted candidate; it is not a schema or meaning validator. Avoid claiming that a clean diff proves the source is complete when the baseline itself may be incomplete.

Finally, parse recovered JSON with a JSON parser, not eval. MDN's JSON.parse documentation describes the parsing boundary. Maintain separate permission checks for actions described by the result. A trustworthy recovery workflow can explain which bytes changed, which facts were checked, and why unresolved uncertainty prevented acceptance.

Frequently Asked Questions

Does repaired JSON prove that the original data was recovered?
No. Repair can make malformed text parseable without establishing the author's intended values or restoring missing content. Acceptance requires separate checks for the selected source, completeness, expected structure, and application rules. If reliable evidence cannot distinguish plausible interpretations, reject or quarantine the candidate and obtain a fresh response or authoritative copy.
Can a JSON repair tool restore records lost during truncation?
Not from absent text alone. Closing an array or string can produce a valid candidate containing only the available prefix. Check independent record counts, identifiers, completion signals, or authoritative source data before calling the result complete. Never pad missing business records with invented values merely to satisfy a schema or count.
Does the JSON Fixer validate my application schema?
No. The fixer repairs common syntax problems and reports detected categories for review. Its valid result flag concerns parsing, not your required fields, allowed types, relationships, or permissions. Apply your own schema validator and application checks to the repaired candidate before accepting it, and keep failed candidates out of trusted processing.
Should repaired data be passed to eval to interpret it?
No. Parse JSON with a JSON parser rather than treating recovered text as executable code. Repair output remains untrusted data and needs ordinary validation and safe handling. A parser succeeding does not authorize commands, updates, or other actions described by the data; enforce those decisions through the application's established permission boundaries.
Is a repair tool's note list a complete edit log?
Not necessarily. This fixer's notes identify categories it detected, not a guaranteed list of every character change or a proof of intended meaning. Preserve the original and candidate separately, compare them in context, and retain the tool version and acceptance decision when auditability matters. Handle sensitive source material under an appropriate retention policy.

Repair a copy, then review it

Inspect a sanitized malformed example in the fixer, preserve the original, and apply independent acceptance checks before using recovered values.

Open JSON Fixer