From JS Object to JSON: Quote the Keys, Drop the Trailing Comma, Get Strict JSON
Turn a JavaScript object literal into valid JSON: quote bare keys, swap single quotes for double, strip trailing commas and comments. With a worked example.
From JS Object to JSON: Quote the Keys, Drop the Trailing Comma, Get Strict JSON
You copy an object out of a .js file, paste it into a fixture, and JSON.parse throws on the first character. The shape looks right, the data is right, but the syntax is JavaScript, not JSON. The two formats look almost identical, which is exactly why the gap trips people up. A JS object literal lets you skip quotes on keys, use single quotes on strings, leave a comma dangling after the last property, and scatter comments between fields. Strict JSON forbids all four. This post walks through what actually has to change to go from one to the other, and shows a converter that does the whole pass for you.
The four rules JSON enforces that JS does not
Most "invalid JSON" errors come down to the same short list of differences. Knowing them by heart saves you a lot of squinting at red error messages.
- Bare keys must get double quotes. In JS,
{name: 'Ada'}is fine becausenameis a valid identifier. JSON has no concept of an unquoted key, so every property name needs wrapping:"name". This is the single most common reasonJSON.parsefails on copied code. - Single quotes become double quotes. JS treats
'hello'and"hello"as equivalent string delimiters. JSON only accepts double quotes, so a value or a key written with single quotes has to be rewritten, and any double quote already living inside that text has to be escaped so the result still parses. - Trailing commas have to go.
{a: 1, b: 2,}and[1, 2, 3,]are legal in modern JS and even encouraged for cleaner git diffs. JSON rejects the comma after the last item outright. - Comments must be stripped.
// lineand/* block */comments are everywhere in config files and documentation snippets. JSON has no comment syntax at all, so they are removed entirely.
There are smaller traps too. NaN and Infinity are valid numbers in JS and in JSON5, but strict JSON has no way to represent them, so they end up as null. If one of those values carries real meaning, swap it for a concrete number before you convert, not after.
A worked example
Here is the kind of thing you actually paste, straight from a console log or a docs page:
{
name: 'Ada', // first user
age: 36,
roles: ['admin', 'editor',],
active: true,
notes: "it's fine",
}
Four separate problems live in that block: the keys have no quotes, two strings use single quotes, the roles array and the outer object both end in a trailing comma, and there is a // first user comment. Run it through the converter and you get strict JSON:
{
"name": "Ada",
"age": 36,
"roles": ["admin", "editor"],
"active": true,
"notes": "it's fine"
}
Every key now wears double quotes. 'Ada' became "Ada", and "it's fine" kept its apostrophe untouched because the single quote there is just a character inside a double-quoted string, not a delimiter. Both trailing commas are gone, and the comment vanished with the data left intact. That last point matters: a converter that naively deletes // would also break a URL like "http://example.com" sitting inside a string. A proper tokenizer knows the difference between a comment marker in code and the same characters inside a string value. You can try the conversion yourself at JS Object to JSON.
Why not just eval it?
The tempting shortcut is eval('(' + text + ')') or new Function('return ' + text). Both turn the string into a real object in one line, and both are a genuinely bad idea for anything you did not type yourself. eval does not parse data, it executes code. If that pasted "object" hides a function call, a network request, or a property getter with a side effect, you just ran a stranger's code with your own privileges. A teammate forwarding you a chunk of "JSON" that is really a JS object should never cost you an eval.
The safe path is a hand-written tokenizer and a recursive-descent parser that only ever produce plain data structures. It reads the input character by character, recognizes strings, numbers, booleans, null, objects and arrays, and refuses to do anything else. No code path in it can call a function or reach the network, so even a sketchy snippet converts to inert data you can inspect before it goes anywhere near your codebase. The converter I'm describing runs entirely in the browser tab on exactly this principle: the input never leaves the page, and nothing in it ever executes.
Where this comes up in real work
I keep this converter pinned because the same situation recurs across totally unrelated tasks. The first is debugging: I expand an object in DevTools, hit "Copy object", and want it in a test fixture, but Chrome copies it as a JS literal with unquoted keys. The second is config migration. A build tool that used to swallow JSON5 tightens up and demands strict JSON, and suddenly a file full of explanatory comments and trailing commas no longer loads. Pasting the whole file and converting in one pass beats hand-deleting commas line by line, and I keep the commented original in source control where it belongs. The third is documentation. API docs love to show request bodies as JS objects with bare keys and inline comments, and copying one into Postman means stripping all of that out first.
The honest first-person admission: I used to fix these by hand, retyping keys with quotes and hunting for the dangling comma the parser complained about. On a ten-property object that is two minutes of fiddly, error-prone editing, and I'd routinely miss one nested trailing comma and have to go around again. Letting a tokenizer do the mechanical rewrite turned a recurring annoyance into a paste-and-copy.
After the conversion: format, shrink, or transform
Getting valid JSON is usually step one, not the finish line. Once the syntax is clean, the next move depends on where the data is headed.
If you want it readable, with consistent two-space indentation and sorted structure, run it through a dedicated JSON Formatter to pretty-print and validate it in one place. If the destination is a network payload or an inline config string where every byte counts, do the opposite and strip all the whitespace with a JSON Minifier. When the goal is a spreadsheet or a quick scan of tabular records, JSON to CSV flattens an array of objects into columns. And if your starting point was never an object literal at all but a URL's worth of key=value pairs, Query String to JSON handles that conversion instead.
The mental model worth keeping: a JS object literal is source code that looks like data, and JSON is data that happens to be valid source in some languages. The conversion between them is purely mechanical, four small rewrites applied carefully enough not to touch the contents of your strings. Once a tool handles that pass reliably, "paste this object and give me real JSON" stops being a chore and becomes a single click.
Made by Toolora · Updated 2026-06-13