To validate JSON from the command line, pipe it through jq empty for a fast validity check, add -e when scripts must fail on bad input, and use a short Python script when you need schema checks or large files. The three recipes below cover all of it.

A deployment failed last month because a config file had a trailing comma. The error surfaced three steps later as a cryptic crash, not a parse error. Five seconds of validation up front would have pointed at the exact line.

This guide shows three command-line validation recipes: jq for quick checks, jq with exit codes for scripts, and Python for schema checks and large files. Use whichever fits the job.

Quick Answer: How Do You Validate JSON From the Command Line?

Run jq empty file.json. Silence means valid JSON; an error with a line and column number means invalid. In scripts, use jq -e . file.json > /dev/null so the exit code tells you the result. For schema checks (required keys, value types), use the Python script in the schema section below.

What Does “Valid JSON” Mean Here?

Valid means the text parses as JSON: quoted keys, no trailing commas, no comments, one complete value. Validation does not check whether the content is correct for your application. A file can be valid JSON and still have the wrong keys, which is why the schema recipe exists.

Prerequisites

  • A terminal on Linux, macOS, or Windows with WSL. The jq examples assume a Unix-style shell; PowerShell quoting differs (see the jq manual note on quoting).
  • jq 1.6 or later for recipes 1 and 2 (see the jq manual). Check with jq --version.
  • Python 3.8 or later for recipe 3 (it uses only the standard-library json module). Check with python3 --version.

Method 1: Fast Validity Check With jq

The jq manual documents that a program consisting of just . reads, validates, and pretty-prints its input. The empty filter goes one step further: it parses the input and produces no output, so you get a pure pass/fail signal.

# Valid file: silent, exit code 0
jq empty config.json && echo VALID

# See the parsed content pretty-printed instead
jq . config.json

When the file is broken, jq points at the problem:

$ jq empty broken.json
parse error: Expected value before ',' at line 1, column 34

Validate every *.json file in a directory before a deploy:

for f in *.json; do
  jq empty "$f" > /dev/null 2>&1 || echo "INVALID: $f"
done

Method 2: Exit Codes for Scripts With jq -e

jq empty already exits non-zero on invalid input, but it prints nothing on success, which makes intent unclear in scripts. The documented -e / --exit-status flag sets the exit status from the last output value (0 for normal output, 1 for false or null, 4 for no valid result), so combine it with a filter that asserts what you need:

#!/bin/sh
# Fail the build if app config is invalid or missing the version key
jq -e 'select(.version | type == "string")' app.json > /dev/null || {
  echo "app.json is invalid or has no version string" >&2
  exit 1
}

Common mistake: piping jq output to grep and checking grep’s exit code instead of jq’s. Keep jq as the last validation step or capture its status with PIPESTATUS in Bash.

Method 3: Schema Checks and Large Files With Python

jq answers “does it parse.” Python answers “does it have the shape my app needs.” This script checks required keys and value types, and it streams large files instead of loading them whole. Tested with Python 3.14; only the standard library is used.

import json
import sys

REQUIRED = {"name": str, "ports": list}

def validate(path):
    with open(path, encoding="utf-8") as fh:
        try:
            data = json.load(fh)
        except json.JSONDecodeError as exc:
            return "invalid JSON: line %s column %s: %s" % (exc.lineno, exc.colno, exc.msg)
    if not isinstance(data, dict):
        return "top level must be an object"
    for key, kind in REQUIRED.items():
        if key not in data:
            return "missing required key: %s" % key
        if not isinstance(data[key], kind):
            return "key %r must be %s" % (key, kind.__name__)
    return None

for path in sys.argv[1:]:
    error = validate(path)
    print(("INVALID %s: %s" % (path, error)) if error else ("VALID %s" % path))

For files too large to fit comfortably in memory, parse incrementally. The simplest honest approach is jq --stream, documented in the jq manual for large inputs, or Python’s json.JSONDecoder().raw_decode in a loop. If your file is under a few hundred megabytes, plain json.load is fine and far easier to read.

Common Mistakes

  • Trailing commas. Valid in JavaScript and Python, forbidden in JSON. The most frequent cause of “works in my editor, fails in the pipeline.”
  • Comments. JSON has no comments. Strip them before parsing or switch the config format to JSON5/YAML if humans edit it by hand.
  • Wrong quoting in the shell. Always single-quote jq programs on Unix shells. In PowerShell, single-quote the program and backslash-escape inner double quotes, per the jq manual.
  • Validating the wrong file. Validate the artifact you deploy (the rendered template output), not the template source.

Troubleshooting

  • jq says “parse error” with no line number context: run jq . file.json | head to see how far the pretty-printer gets; the break point is near the fault. Our JSON errors troubleshooting guide covers the most common messages.
  • Python reports “Expecting property name”: usually a trailing comma or a single-quoted string. JSON strings need double quotes.
  • Encoding errors on both tools: confirm the file is UTF-8 (file -i config.json on Linux). A BOM or Windows-1252 smart quotes break parsers.

Security Considerations

Never pipe untrusted JSON through eval or equivalent in any language; parsed data is data, not code. When validating uploads, cap file size first (head -c or a web-server limit) so a multi-gigabyte payload cannot exhaust memory before the parser rejects it.

Alternatives

  • Online validators such as the JSON Formatter or JSON Validator on tools.devstackio.com for one-off checks where pasting is acceptable. Do not paste secrets or customer data into any hosted tool.
  • Editors and CI plugins (VS Code JSON language mode, jsonlint steps) for continuous feedback rather than pre-deploy gates.
  • Strict schemas with jsonschema (third-party package) when contracts matter more than ad-hoc key checks — or generate a starter schema from sample data with the JSON Schema Generator.

FAQ

How do I validate JSON and pretty-print it at the same time?

Run jq . file.json. If the input parses, jq prints it formatted; if not, it prints the parse error. Redirect to a new file to keep the formatted copy.

How do I check JSON inside a Bash script without printing anything?

Use jq -e . file.json > /dev/null and test $?. Exit code 0 means valid. The -e flag is documented in the jq manual under invoking jq.

jq is not installed. What is the shortest Python equivalent?

Run python3 -c with json.load, or save the validation script from this guide. Python ships with every mainstream Linux distribution and macOS, so it works on machines where you cannot install packages.

How do I validate a 2 GB JSON file?

Use jq --stream for path-by-path processing, or split the producer output into newline-delimited JSON (one object per line) and validate each line. Loading the whole file with json.load will exhaust memory on small machines.

Related DevStackIO Resources

Method note: jq behaviors cited from the jq 1.8 manual (checked 2026-09-20); the Python script uses the standard json module and was executed locally on Python 3.14. jq was not installed on the test machine, so jq command shapes are manual-verified, not execution-verified.

Related Tools

Try these companion tools on DevStackIO Tools: