Payload Validator

Payload Validator / JSON

Validate JSON

Reports every problem in one pass with a 1-based line and column, including the three that JSON.parse cannot report at all: duplicate keys, integer precision loss, and unpaired surrogates.

Up to 6,000 characters here, because this form puts the payload in the URL. For anything larger, POST it to the API — the limit there is 1 MB. Nothing is stored either way.

Valid JSON

0 errors, 1 warning

bytes:
11
objects:
1
arrays:
0
keys:
1
strings:
0
numbers:
1
max depth:
1

1 finding

What goes wrong in JSON

Duplicate keys are accepted and one value silently disappears

{"port": 8080, "port": 9090}

RFC 8259 says names SHOULD be unique and does not say what happens when they are not. JavaScript and Python keep the last, some Go and Rust decoders error, and others keep the first. The document genuinely has no single meaning, and no parser will tell you — JSON.parse returns one port and no warning.

json.duplicate_key · run this example

A 64-bit ID becomes a different number

{"id": 9007199254740993}

JSON numbers are IEEE-754 doubles in nearly every parser, exact only up to 9007199254740991 (2^53-1). Anything larger silently rounds: that ID parses as ...992. Snowflake IDs from Twitter and Discord, and most database bigints, are all in the lossy range. It is why the Twitter API added id_str alongside id. Send large integers as strings.

json.number_precision_loss · run this example

Trailing commas are valid JavaScript and invalid JSON

{"a": 1, "b": 2,}

Every formatter, linter and JS engine accepts a trailing comma, and JSON5 and JSONC make it legal, so the habit is well trained. Plain JSON forbids it.

json.trailing_comma · run this example

Python repr output looks like JSON and is not

{'ok': True, 'missing': None}

Single quotes, True, False and None are Python, not JSON. This happens whenever str(dict) or an f-string is used where json.dumps() was meant. JSON's literals are lowercase and there are exactly three: true, false and null.

json.non_standard_literal · run this example

NDJSON is not JSON

{"a":1}
{"a":2}

A JSON document holds exactly one top-level value. Newline-delimited JSON is one document per line and must be validated a line at a time — reading the whole file as a single document fails on the second line, every time.

json.trailing_content · run this example

A byte order mark is invisible and forbidden

{"a": 1}

RFC 8259 forbids a BOM in JSON text and strict parsers reject the document. It is invisible in every editor, so the file looks perfect. Save as "UTF-8" rather than "UTF-8 with BOM".

json.byte_order_mark · run this example

Call it instead of pasting

curl --data-binary @your-file \
  'https://payload-validator.gumballtools.com/api/v1/validate?format=json'

API and MCP setup — the MCP tool is validate_json.

Other formats