creatorvalet

Convert a JavaScript object to JSON

Parsed, never evaluated. Everything JSON cannot hold is listed with its path — not dropped in silence.

Runs in your browser0 bytes uploaded
Waiting
Size
Keys
Not in JSON
Depth

Nothing you paste is executed. The text is parsed character by character — there is no eval here, so a snippet someone sent you cannot run just because you looked at it.

Indent
Keys

Source order is the default because it keeps the file diffable against the one you started from. Sorting helps when you are comparing two objects by eye.

№ 9591waiting

Nothing at the counter yet. Paste a JavaScript object, drop a .js file anywhere on the panel to the left, or press Use an example.

Most converters solve this by running your code

Turning a JavaScript object into JSON is a one-line job if you are allowed to cheat. Evaluate the text, hand the resulting value to JSON.stringify, print what comes back. It handles comments, single quotes, unquoted keys, trailing commas and every other convenience of the language, because the language itself is doing the reading. A surprising number of online converters do exactly this, and it works right up until it does not.

The problem is that a JavaScript object literal is not a passive thing. Anywhere a value can appear, an expression can appear, and an expression can call a function. Paste{ total: getTotal() } into an evaluating converter andgetTotal runs. Paste an immediately-invoked function and it runs too, with whatever the page can reach — network access included. This matters because of where these snippets come from: a colleague's message, a bug report, a Stack Overflow answer, a minified bundle you are trying to understand. You are pasting it precisely because you do not yet know what it does. A tool that answers that question by running it has the order backwards.

This one reads the text character by character and builds a value from what it finds. There is no eval, no new Function, and no worker that imports your snippet as a script. A function in the input is recognized as a function and reported as one; it is never called. That is a smaller promise than "your data never leaves the browser" — which is also true here — but it is the one that actually protects you, because code that runs locally still runs.

What a JavaScript object to JSON conversion cannot carry

JSON has exactly six kinds of value: object, array, string, number, boolean and null. A JavaScript object can contain far more than that, and everything outside those six has nowhere to go. The usual behavior, and what JSON.stringify itself does, is to silently discard it — a key whose value is undefined disappears from the output, a function disappears, and you find out later when something downstream reads a field that is not there.

Nothing here disappears without a line about it. Every value that cannot cross is listed with the path it sat at — settings.retry.onError, not just "a function" — plus the line, the column, and the source text as you wrote it. Alongside each one is what to substitute: a function becomes the value it returns, an uncalled expression becomes the value it produces, a regular expression becomes its pattern as a string, andundefined becomes null if the key should survive at all. Inside an array the slot becomes null so the indexes do not shift; inside an object the key is removed. Both of those match what JavaScript does. The difference is that you are told which one happened and where.

NaN and Infinity get their own treatment: they becomenull with a warning, because JSON genuinely has no notation for either and null is the only defensible substitute. A key that appears twice keeps its last value, as the language would, and a warning names the key and its line — a duplicate key is nearly always a merge accident, and the value you see first in the file is not the one you get.

The syntax it accepts

Everything JSON5 allows, plus the shapes people actually paste. Line and block comments. Single quotes and backticks as well as double. Property names written bare, quoted, or as numbers. Trailing commas in objects and arrays. Hexadecimal, binary and octal numbers, numeric separators like 1_000_000, a leading plus sign, and numbers that begin with a decimal point. Empty slots in an array.

It also strips the wrapper. Real snippets rarely start at the opening brace — they start atconst settings = {, or export default {, ormodule.exports = {, and a converter that demands you delete the left-hand side first is making you do the tedious part of its job. Paste the whole line, semicolon included. What it will not accept is a second value after the first: JSON holds one document, so two objects in a row is an error rather than a guess about which one you meant.

When the input cannot be parsed at all, the message says what was wrong in words. An unterminated string, an unclosed block comment, a missing colon after a property name and a missing comma between two values each have their own explanation, and all of them come with a line number, a column, the surrounding source and a caret under the exact character. This is the same error reporting as the JSON formatter, for the same reason: Unexpected token } tells you nothing you did not already know.

Which direction do you actually want?

The two conversions are not symmetric, and it is worth knowing which side of the asymmetry you are on. JSON to a JavaScript object can always succeed, because everything JSON can express is expressible in JavaScript; the only thing that tool has to be careful about is quoting the property names that need quotes. Coming back the other way is lossy by nature, which is why this page spends most of its effort on telling you what was lost.

If what you have is already valid JSON and you only want it tidied, sorted or validated, neither tool is the shortest path — the formatter does that without changing the format. And if the destination is a spreadsheet rather than a program,JSON to CSV is the one that flattens the nesting and lets you decide what happens to the arrays.

Nothing leaves this tab

The parser is a few kilobytes of JavaScript running in the page you are reading. There is no upload endpoint, so there is nowhere for your snippet to go. Open your browser's Network tab and paste something in: no request appears. Combined with the fact that nothing you paste is executed, that gives you both halves of the guarantee — the code does not leave, and the code does not run.

Questions

Does this run the JavaScript I paste?

No. The input is read by a parser that walks the text character by character and builds a value from it. There is no eval, no new Function, and no Web Worker that imports your snippet as a script. This matters more than it sounds: several well-known converters do evaluate the input, which means a snippet a colleague sent you, or one copied out of a bug report, executes the moment you paste it in to look at it. In those tools an expression like (() => fetch("https://example.com"))() is not data — it is code that runs. Here it is text that gets reported as unsupported and skipped.

What happens to functions, undefined and dates?

They are reported, never dropped in silence. JSON has exactly six kinds of value — object, array, string, number, boolean and null — so a function, an undefined, a regular expression, a bare variable name or a call like new Date() has nothing to become. The receipt lists each one with the path it sat at, the line and column, and the source text, so you can decide what to substitute. Inside an array the slot becomes null, which is what JSON.stringify does too; inside an object the key disappears, which is also what JSON.stringify does. The difference is that you are told.

Which non-JSON syntax is accepted?

Line and block comments, single quotes and backticks, unquoted and numeric keys, trailing commas, hexadecimal, binary and octal numbers, numeric separators like 1_000_000, a leading plus, numbers starting with a dot, NaN and Infinity, and a wrapping declaration such as const data =, export default or module.exports =. That covers JSON5 plus the shapes people actually paste out of a console log or a config file. NaN and Infinity become null with a warning, because JSON has no way to write them.

What if the same key appears twice?

The last one wins, exactly as it does when JavaScript evaluates the literal, and a warning names the key with its line number. This is worth knowing because a duplicate key is almost always a merge accident, and the value you see first in the source is not the one you get. Plain JSON parsers behave the same way but say nothing about it, which is how a config file can quietly use a setting you thought you had overridden.