DEV Community

Anuj Kabra
Anuj Kabra

Posted on

Formatting a JSON blob full of customer data without sending it anywhere

When an API response comes back as one long line, the quick fix is to paste it into a web formatter. The trouble is what that line usually holds: a bearer token, a customer email, an internal ID, sometimes an address. Some online formatters send the paste to a server to format it, and once it has left your machine you can't take it back. Formatting JSON needs nothing more than a parser you already have. Below are the commands I use, how to read the errors, and one precision gotcha that bites browser-based formatters.

Everything here was run on a dummy file with made-up values (test@example.com, a fake order ID), using jq 1.7, Python 3.13 and Node on Linux.

Format with jq

jq . response.json
Enter fullscreen mode Exit fullscreen mode

The . is the identity filter: jq reads the document and prints it back indented by two spaces. Some useful variants:

jq -S . response.json        # sort keys alphabetically
jq --indent 4 . response.json
jq -c . response.json        # compact, one line (minify)
jq '.data.items[0]' response.json   # print just one part
Enter fullscreen mode Exit fullscreen mode

If the JSON is on your clipboard rather than in a file, pipe it in: pbpaste | jq . on macOS, or xclip -o -selection clipboard | jq . on Linux with xclip installed.

Format with Python (already on most machines)

python3 -m json.tool response.json
Enter fullscreen mode Exit fullscreen mode

That prints with four-space indents. --indent 2 changes the width, --sort-keys sorts keys, and --compact gives the one-line form. No install needed beyond Python itself.

Reading the error when the JSON is broken

Both tools point at the problem instead of just refusing. With a trailing comma, {"a":1,}, I got:

python3: Illegal trailing comma before end of object: line 1 column 7 (char 6)
jq:      parse error: Expected another key-value pair at line 1, column 8
Enter fullscreen mode Exit fullscreen mode

The usual causes in hand-edited or logged JSON are trailing commas, single quotes instead of double quotes, comments, and a log prefix (a timestamp or DEBUG:) stuck in front of the opening brace. JSON allows none of those.

The gotcha: big integers in a browser formatter

JavaScript stores every JSON number as a 64-bit float, so integers above Number.MAX_SAFE_INTEGER (9007199254740991, which is 2^53 - 1) can't all be represented exactly. A formatter that runs JSON.parse and then JSON.stringify will quietly change them. I fed this file through each route:

{"order_id": 12345678901234567890, "amount": 1.10, "email": "test@example.com", "ok": true}
Enter fullscreen mode Exit fullscreen mode

What came out for order_id and amount:

  • Node, JSON.parse then JSON.stringify: 12345678901234567000 and 1.1. The ID is now a different number, and nothing warned me.
  • jq 1.7, jq .: 12345678901234567890 and 1.10, exactly as written. jq 1.7 keeps the original text of a number literal it doesn't modify. Do arithmetic on it (jq '.order_id + 0') and it rounds to 12345678901234567000 again, and older jq releases round on plain formatting too, so check jq --version.
  • Python, json.tool: 12345678901234567890 (Python integers have no size limit) but 1.1, because floats are re-printed in their shortest form.

So if your data has 64-bit IDs (Twitter-style snowflake IDs, some database keys, payment references), a browser formatter can show you a wrong ID that looks perfectly plausible. Many APIs send such IDs as strings for exactly this reason. When you see one as a bare number, trust jq or Python for the value, not a JavaScript page.

If you do use a web page

  1. Load it, then turn the network off and check it still formats. A page that keeps working offline is doing the work in your tab.
  2. For a stricter check, keep DevTools open on the Network tab while you paste and format, and look for any request carrying your text. I wrote up that check in more detail in How I check whether a "no upload" PDF tool really keeps my file local; the same steps apply to any paste box.
  3. Your employer's data policy still applies, even when nothing leaves the tab.

I built ToolOcean, and it has a JSON formatter that runs in the browser. Its page says the formatter keeps working with the network disconnected once loaded and that nothing is stored. I read its shipped code before writing this: it formats with the browser's own JSON.parse and JSON.stringify, so the big-integer rounding above applies to it too. For a file with 64-bit numeric IDs, use jq. The page is toolocean.co/json-formatter-offline.

Drafted with AI help, tested and checked by me.

Top comments (0)