Files, Encodings & Formats

Validate JSON and find the syntax error on Mac

You can do this with Note My, on your own machine rather than in somebody's website. Here is how to validate the file, read the position it reports, and track down the character that actually broke it.

Something has rejected your JSON. A build step, an API, a configuration loader — and the message is Unexpected token or simply invalid JSON, with no line number attached. The file looks fine. It is four hundred lines long, and exactly one character in it is wrong.

This guide covers how to validate a JSON file in Note My, how to read the position it reports, and how to find the kind of character that breaks a strict reader without looking broken on screen.

Note

The check runs on your Mac. Nothing is uploaded, there is no account to create, and the file never leaves the machine — which matters when the thing that will not parse is a configuration file with credentials in it.

What Validate JSON tells you

Edit ▸ Validate JSON tells you, in an alert, whether your text is valid JSON. It never changes a character of your document, which makes it safe to run on a live configuration file.

It settles the question standing between you and a build that will not start: does this text parse as JSON? When the answer is yes, you can stop suspecting the punctuation and go and look at the values instead. When the answer is no, you are handed a line and a column to walk to, which is the difference between a two-minute repair and an afternoon spent reading four hundred lines one at a time.

Three details are worth knowing before you run it:

  • Scope is the selection if there is one, otherwise the whole document. The same rule applies to Format JSON, Minify JSON, Format XML and Minify XML.
  • Nothing is changed when the check fails. That is true of the formatting commands too — a Format that cannot make sense of the text leaves your document exactly as it was.
  • An empty scope says so. With nothing to work on you get "There's no content to format…" rather than a misleading pass. Text that cannot be read at the encoding currently in use gets its own message — see the encoding note in Troubleshooting.

Validate a file

  1. Open the file

    Press ⌘O, or drag the file from the Finder onto the tab bar. If the file has an extension macOS has assigned elsewhere, or no extension at all — a .conf, a .lock, a rotated copy called settings.json.bak — press ⇧⌘O for File ▸ Open Anything as Text… and it opens regardless.

  2. Decide what you are checking

    To check the whole file, make sure nothing is selected. To check one object inside a larger file — a JSON blob embedded in a log line, one entry from a list — select exactly that text first. The command uses the selection when there is one.

  3. Choose Validate JSON

    Go to Edit ▸ Validate JSON. The answer comes back at once, in an alert you read and dismiss. A file that parses is confirmed in a sentence; a file that does not hands you the position of the first thing that stopped it.

  4. Read the position out of the message

    When the text is not valid JSON, the alert names a position in the form (around line N, column M). Note the two numbers before you dismiss the alert. The next step takes you straight there.

  5. Go to the line

    Press ⌘L. The sheet reads "Enter a line number between 1 and N" and arrives pre-filled with the line you are currently on, selected, so you can type over it. Enter the reported line. An out-of-range or non-numeric entry beeps rather than quietly clamping to the nearest valid line, so you always know whether the jump happened.

  6. Fix it and run Validate again

    Validate reports the first thing that stopped the parse, which gives you a clean rhythm to work in: fix, check again, fix the next. Run it once more even when you are confident the file is clear, because a second mistake is often introduced by the first repair, and the second pass costs you a single menu item.

Reading "around line N, column M"

The word around is doing real work in that message, and it is worth taking at face value rather than trusting the number blindly.

The position you are given is where the text stopped making sense, which is frequently one step past the point at which you went wrong. A missing comma is reported not at the end of the line that should have carried it, but at the start of the next key, where a comma was due and a string turned up instead. A quotation mark you never closed is reported wherever the run-on string finally meets something illegal, which can be many lines further down.

So treat the reported position as the end of a range, not a pinpoint. Look at the character named, then read upwards: the end of the previous value, the previous line's final character, the last closing brace. The fault is usually just above the number you were given.

Tip

Double-click a brace to fold the block it opens, and collapse the objects you have already cleared. Folding works on {}, () and [], and never changes a character of the document.

What usually broke it

JSON is a small format with a short list of things it refuses. Most invalid files fail for one of these reasons, and they split into the ones you can see and the ones you cannot.

Common causes of a JSON parse failure and how visible each one is
CauseVisible on screen?
A trailing comma after the last item in an object or arrayYes, once you look
A key or string wrapped in single quotes rather than doubleYes
An unquoted keyYes
A comment — JSON has noneYes
A missing comma between two entriesYes, but easy to skim past
A curly quote where a straight one belongsBarely — the shapes are similar
A non-breaking space instead of a spaceNo
A zero-width or bidirectional control characterNo
The file decoded with the wrong encodingSometimes, as garbled accents

Finding a character that looks correct

The three rows you cannot simply read off the screen are the ones that cost people an afternoon — the fourth, a file decoded with the wrong encoding, is dealt with in Troubleshooting below. Three tools handle the invisible ones, and they cover different ground.

The hidden-character pill

The status bar carries a pill, backed by our hidden-character scanner, that keeps you posted while you work. It reads Clean in green when there is nothing to report, "N hidden" in orange, or "N hidden · D risky" in red. Click it and the popover offers Show in Text, Remove Invisible Character(s), Review All… and Go to Next, plus switches for Protect Strings & Comments and Check While Typing. Only findings that are wrong anywhere — zero-width characters, control characters, stray separators — are offered for one-click removal.

The pill is precise about what it raises, which is why its colour is worth trusting. It stays quiet on a curly quote, because a curly quote is a perfectly legitimate character in prose, and a pill that turned orange every time you typed an apostrophe would be telling you nothing. When punctuation is what you are hunting, the full sheet is where to go.

The Review All sheet

Open Clean ▸ Clean Invisible / Special Characters…. Choose a scope — Selection or Whole Document — pick a preset and press Scan. The left table lists all twenty-one categories with a severity chip and a count; the right table lists every finding as Line:Col · Code Point · Category · Action · Risk. Double-click a finding to reveal it in the editor, or use Show in Editor in the footer. Apply (N) commits, Close walks away.

Preset choice matters here. Code-safe, the default, covers sixteen categories and includes smart quotes, smart dashes and the ellipsis character — but it reports them without rewriting them. Only Aggressive, which enables all twenty-one, converts smart punctuation to plain ASCII. So when straight quotes are what you are after, pick Aggressive from the preset pop-up before you press Scan, and a single Apply turns every curly quote, en dash and ellipsis character in the scope into its plain equivalent. The scope control at the top of the sheet still applies, so you can convert one selected block and leave the rest of the file exactly as you found it.

Clean ▸ Find Next Hidden Character and Clean ▸ Find Previous Hidden Character step through the findings one at a time, so you can look at each one in its context and decide what it deserves before you touch it.

A single find and replace

For one known character, our find and replace is quicker. Open the toolbar's Find & Replace popover, paste the offending character into the find field and type a straight one into the replace field. The options are Case Sensitive, Whole Word and Regular Expression; with the last of those on, a single character class catches every quote variant in one pass.

Once it parses

Edit ▸ Format JSON reprints the document with two-space indentation, and it sorts the keys — worth knowing before you run it on a file under version control, because the values are unchanged but the diff can be large. ⌘Z reverses it. Edit ▸ Minify JSON goes the other way. Both obey the same selection-or-document scope, and both behave like any edit you made by hand, with our auto-recovery safety net looking after the document.

Checking XML in the same place

The same Edit menu carries Format XML and Minify XML, and Format XML doubles as the check for an XML document. Run it and read the result: if the document reprints itself, indented and readable, it was well formed. If the text cannot be made sense of, your document is left exactly as it was — nothing is half-rewritten — so trying it costs you nothing at all.

Minify XML goes the other way, collapsing a formatted document back down for a payload or a config that only a machine is going to read. Both obey the same selection-or-document scope as their JSON counterparts, so you can reformat a single element inside a large file by selecting it first and leaving the rest of the document untouched.

Working through more than one file

A single broken file is rarely the whole job. A deployment brings a folder of configuration with it, and the one that will not parse is somewhere among the others.

Start with Search ▸ Find in Folder… (⇧⌘F). It searches every text file under a folder you choose — for a key, a value, or a fragment of punctuation you now suspect — and it only ever reads them. Nothing under that folder is written, so you can point it at a live deployment directory without a second thought. Use it to narrow four hundred files down to the six that carry the setting you changed, then open those six and check them.

When you have a file that works and a file that does not, our comparison view puts the two side by side and marks what differs. That is often quicker than reading either one closely: a stray character, a duplicated block or a value that was never meant to change announces itself as a difference rather than as something you have to notice.

Inside a long file, work from the top down and shrink what you have already cleared. Double-click a brace to fold the block it opens, and every object you have satisfied yourself about collapses to a single line, leaving the part you are still suspicious of on screen by itself. A large export or a captured payload opens exactly like anything else, with our large-file engine keeping the document responsive while you scroll and search.

And when the same fault turns up in file after file — the same curly quote pasted from the same document, the same key spelled the same wrong way — our find and replace with Regular Expression switched on clears every instance in the file in a single pass, and ⌘Z takes the whole pass back if you have second thoughts.

Troubleshooting

The reported line looks perfectly fine

Read upwards. The position you are given is where the text stopped making sense, and a missing comma, an unterminated string or an extra closing brace all show themselves after the fact. Check the end of the previous value and the previous line's final character before you doubt the line you are on.

Validate says there is nothing to format

The scope is empty. Either the document is empty, or you have a zero-length selection somewhere the command is reading as the scope. Click into the text so nothing is selected, then run it again on the whole document.

The message says the text is not UTF-8

The bytes on disk were written in another encoding. Use File ▸ Encoding ▸ Reload with Encoding… and choose the one the file was actually written in — Windows-1252 covers a lot of older Western text, and Shift JIS, EUC-JP, GB18030 and Big5 are there for CJK. Reloading changes nothing on disk — it only changes how the file is shown to you, so you can try one and then another. Convert to Encoding… is the opposite operation: it changes what gets written when you next save. Our encoding handling keeps the two apart, so opening a file the wrong way round is never destructive.

The tool at the other end chokes on the first character

Suspect a byte-order mark. The encoding list treats UTF-8 and UTF-8 with BOM as two separate encodings, and the status-bar encoding pill tells you which one this document is. Preserve BOM is on by default in Settings ▸ Encoding, so a file that arrived with a mark keeps it through a save and the decision about it stays yours. When the tool at the other end would rather not have one, use File ▸ Encoding ▸ Convert to Encoding… and choose plain UTF-8: that is what gets written from your next save onwards, and the text in front of you is unchanged.

A mark at the very start of a file is legitimate and is left where it is. The same character anywhere else in the document is zero-width junk — usually the seam where two files were concatenated — and our hidden-character scanner lists every one of them under Zero-width characters with a line and column, ready to remove in a single pass.

My straight quotes keep turning curly

Then they were curled somewhere else, because Note My never rewrites your text as you type: no automatic quote substitution, no dash substitution, no text replacement, and paste always arrives as plain text. Which is the point — an editor that helpfully curled your quotes would be creating the exact bug this page is about. If the curly quotes arrived with the text, our hidden-character scanner lists every one of them with a line and column, and the Aggressive preset converts them back to plain ASCII in a single pass.

Format JSON appeared to do nothing

Then the text was not valid JSON, and your document was left exactly as it was — a Format never half-rewrites a file it cannot make sense of. Run Validate JSON to get the position.

Frequently asked questions

Does validating send my JSON anywhere?

It all happens on your Mac. Nothing is uploaded, there is no account to sign in to, and the file never leaves the machine. That is the reason to do this in an editor rather than pasting a configuration file into somebody's web form.

Why does the error point at a line where nothing is wrong?

Because the position you are given is where the text stopped making sense, not where you slipped. A missing comma shows up at the start of the next key; an unterminated string shows up wherever it eventually collides with something illegal. Read from the reported position upwards.

Can I validate just part of a file?

Yes. Select the text first and the command uses the selection instead of the whole document. This is the way to check one JSON blob embedded in a log line or a single entry pulled out of a large list.

Does Format JSON change my data?

It reprints it with two-space indentation and sorts the keys. The values are untouched and the meaning is identical, but the order the file is written in changes, so expect a sizeable diff on a file under version control. One ⌘Z reverses the whole operation.

Can I check an XML file the same way?

Yes. Run Edit ▸ Format XML and read the result. A well-formed document reprints itself, indented and readable, so you get the answer and a tidier file in one move. Text that cannot be made sense of leaves your document exactly as it was, and Minify XML collapses it all again afterwards. Both honour the same selection-or-document scope as their JSON counterparts.

How do I find an invisible character that is breaking the parse?

Watch the status-bar pill, which reads "N hidden" when it finds characters that are wrong anywhere, and use Clean ▸ Clean Invisible / Special Characters… for a full scan of all twenty-one categories with a line and column for every finding. For a curly quote specifically, you need the Aggressive preset — the default reports smart punctuation without converting it.