Start with the boundary that failed

When an API call fails, “the JSON is wrong” is only a first guess. The problem may be malformed JSON, a valid value with the wrong shape, a valid object that violates an application contract, or a value that was transformed before it reached the parser. Keep those possibilities separate. Begin with the exact response or request body at the boundary where the failure occurs. If the only copy came from a log line, confirm whether the logger escaped quotes, removed newlines, or truncated the message. A display string can be different from the original bytes, and a copied fragment may omit the character that made parsing fail.

Next record the surrounding context without exposing credentials: request method, route template, status code, content type, and a request identifier if the system already provides one. Do not copy an authorization header into an online decoder. In a local workbench, keep a minimal synthetic payload that preserves the relevant structure. The useful debugging artifact is not the largest captured body; it is the smallest example that still reproduces the same parse or shape failure.

Syntax is a narrower question than validity

JSON is a text format for values. A JSON value can be an object, array, string, number, Boolean, or null. Objects contain name/value members, while arrays contain ordered values. This matters because an API that expects an object may reject a syntactically valid array or string. A parser answers whether the characters follow the JSON grammar. It does not know the endpoint’s intended fields or business rules. RFC 8259 also warns that object member names should be unique; receivers can behave differently when a document repeats a name.

Common copy-and-paste errors include a trailing comma, a single-quoted string, a comment, an unquoted property name, or an incomplete escape. These forms may look natural in JavaScript source, but they are not part of the JSON grammar. A backslash escape must be valid, and a literal line break cannot appear inside a JSON string. Non-finite values such as NaN and Infinity are not JSON numbers either. A formatter should preserve the in-memory parsed value, not silently “fix” these mistakes by guessing what the author meant.

Read a parser location as a clue

A useful parser error gives a line and column or an offset into the input. Treat that location as a neighborhood to inspect, not a complete diagnosis. Some messages point at the character where parsing stopped; the cause can be a missing quote or delimiter just before it. Different engines phrase errors differently, and positions may count UTF-16 code units rather than visible characters. A non-ASCII symbol can therefore make a manually counted column misleading.

Work from the reported point in both directions. Check whether a string opened earlier is still closed, whether an object member has a colon, and whether the value before a closing brace has an extra comma. If the problem begins after a quoted field, inspect escaped quotes and backslashes. For a deeply nested payload, reformat the valid outer portion in a real JSON parser and then reduce the suspicious value. Do not rely on replacing punctuation globally; the same comma or quote can be meaningful in another string.

Inspect shape before guessing a schema

After parsing succeeds, make a small shape inventory. Is the top level an object or array? How many direct members or items are present? Which values are objects, arrays, strings, numbers, Booleans, or null? A missing member and a member set to null are different observations. An empty array is also not the same as an absent array. Those distinctions often explain why a caller that worked with one response fails on another.

The Benchlight JSON Inspector reports the parsed top-level type and direct-member count. That deliberately narrow summary is helpful when a response unexpectedly changes from an object to an array, or when a payload is valid but empty. It does not validate field names, nested types, required properties, date formats, or application meaning. If a contract matters, write down those expectations explicitly and validate against a versioned schema or the service’s actual contract tests.

Compare the failing value with a known-good one

Put the smallest known-good sample beside the failing sample. Compare paths rather than entire lines: a changed value such as an account name usually does not change the shape, while an identifier changing from a number to a string may affect a client. Look at fields that disappeared, newly appeared, changed type, or moved inside a nested object. Repeated samples help reveal variation, but no finite sample proves that a field is always present or that all possible enum values have been observed.

When the response crosses multiple layers, inspect each layer separately. A database row can be mapped into a service object, serialized as JSON, then wrapped in an HTTP envelope. A client may be receiving the envelope rather than the inner object it expects. Check the actual content type and the exact property path that the client reads. If a proxy or framework transforms output, compare the body immediately before serialization with the body received by the client, using safe local fixtures where production data is sensitive.

Keep diagnostics safe and reproducible

Payloads often contain personal data, access tokens, session identifiers, or internal names. Redact those values before adding an example to an issue or commit. Preserve the type and shape during redaction: replacing a string with another string is less disruptive than replacing it with null. Keep a note of what was redacted so reviewers do not interpret the sample as production evidence. Never paste a live credential into a third-party validator merely because it promises to format JSON.

A reproducible report should include the operation, the expected top-level form, a minimized redacted sample, the observed parser error, and the version of the schema or contract under discussion. Record whether the body was captured before or after a transformation. These details let another engineer reproduce the same boundary without access to production data. The report should state what remains uncertain, such as whether a new field is intentional or whether the failing sample was truncated before capture.

A parseable identifier can still change value

Use this invented payload to separate a syntax repair from a representation problem:

{"invoiceId":9007199254740993,"status":"ready",}

First paste it unchanged into JSON Inspector. The trailing comma makes it invalid JSON. Remove only that comma and run the inspector again. The text now parses, but JavaScript represents the invoice identifier as 9007199254740992. That change is caused by numeric precision, not by indentation or a missing schema. The original integer is outside JavaScript's safe integer range. A successful parse therefore does not prove that every decimal digit survived.

If the interface defines invoice identifiers as opaque strings, a suitable fixture is:

{"invoiceId":"9007199254740993","status":"ready"}

This form preserves the identifier's digits in the current formatter. Do not change a real API's numeric field to a string without coordinating its contract: callers may depend on the existing type. The immediate debugging action is to preserve the raw capture and identify where the conversion happened. Converting the already-rounded JavaScript number back to text cannot reconstruct the lost digit.

Duplicate names expose a different loss. Parsing {"status":"queued","status":"ready"} in this inspector retains the later status. Reformatting that result cannot reveal the discarded occurrence. RFC 8259 recommends unique names because receivers differ in their handling of duplicates. A formatter built on JSON.parse is consequently unsuitable as an archival copy of the original message. Keep raw text for byte-sensitive investigations, signatures, and duplicate-key analysis. Use the formatted value for reading after those preservation needs have been addressed.