.env file

JSON

Why convert a .env file to JSON?

You are staring at a forty-line .env from a service you did not write, trying to work out which variables it actually needs. Or you are moving configuration into a secrets manager that wants JSON, or diffing staging against production and the two files list their keys in a different order. Paste the file here and you get a JSON object back, with the values decoded the same way your application will decode them.

That last part is the bit worth caring about. Most quick conversions do line.split('=') and move on, which breaks the first time a connection string arrives: DATABASE_URL=postgres://user:pw@host:5432/db?ssl=true has four equals signs in it, and splitting on all of them throws away everything after the first. This page splits on the first one only, which is what dotenv and every shell do.

Quoting is the other half. A value in double quotes has its escapes expanded, so "line1\nline2" becomes two lines. A value in single quotes is taken literally, so a Windows path like 'C:\new\table' keeps its backslashes instead of quietly growing a newline and a tab. Getting those two backwards is a bug you will chase for an hour, because the file looks fine and only the running process disagrees.

Nothing you paste leaves the browser. That matters more here than on most pages — a .env is where the credentials live, and the OWASP secrets management guidance is blunt about pasting them into anything that transmits. If you want to share the shape of a config without the secrets, tick Mask values and the keys come through with the values replaced.

How to use it

  1. Paste or upload the file – Drop in the contents of a .env, .env.local, .env.production — anything in KEY=value form. Comments and blank lines are ignored.
  2. Read the JSON on the right – Every key becomes a string property. Values stay strings, because that is what an environment variable is — the process reading it decides whether "5432" is a number.
  3. Check the notices under the input – Lines that are not KEY=value are listed with their original line numbers, and any key defined twice is named.
  4. Sort or mask if you need to – Sorting makes two environments comparable side by side. Masking replaces every value with dots so the output is safe to paste into a ticket.
  5. Copy the result – Use it as a seed for a secrets manager, a config schema, or a checklist of what a service expects to be set.

Values come out as strings on purpose, even when they look like numbers or booleans. An environment variable is always a string at the operating-system level — PORT=5432 arrives at your process as the two-byte-per-character text "5432", and something in your code has to convert it. A converter that guessed types here would hide that step, and hiding it is how DEBUG=false ends up truthy.

A real file, and the parts that trip people up

Every line below is one that a naive parser gets wrong. The connection string has four equals signs. The greeting has a # inside quotes that is not a comment. The password has a # that is not a comment either, because nothing separates it from the word before it. And PRIVATE_KEY_PATH is single-quoted, so its backslashes stay backslashes.

sim-provisioning service.env to JSON
.env9 keys
# SIM provisioning service
DATABASE_URL=postgres://u:pw@db:5432/sims?ssl=true&pool=10
BANNER="line one\nline two"
CERT_PATH='C:\new\certs\hss.pem'
HSS_NOTE="rate limited # see runbook"
PASSWORD=pass#word
export HSS_ENDPOINT=https://hss.internal/v2
MAINTENANCE_BANNER=
output.jsondecoded
{
  "DATABASE_URL": "postgres://u:pw@db:5432/sims?ssl=true&pool=10",
  "BANNER": "line one\nline two",
  "CERT_PATH": "C:\\new\\certs\\hss.pem",
  "HSS_NOTE": "rate limited # see runbook",
  "PASSWORD": "pass#word",
  "HSS_ENDPOINT": "https://hss.internal/v2",
  "MAINTENANCE_BANNER": ""
}

When you would reach for this

Comparing two environments

Staging works, production does not, and the two .env files are 60 lines each in different orders. Convert both with Sort keys on, then put the two JSON documents through JSON Diff. What took ten minutes of scrolling becomes a list of four keys.

Moving configuration into a secrets manager

AWS Secrets Manager, Vault and Google Secret Manager all take JSON. Converting the file is the first step; the second is deciding which of those keys are actually secret and which are just settings, which is much easier to do against a structured document than a flat text file.

Documenting what a service needs

Turn a working .env into JSON, mask the values, and you have an accurate .env.example in about four seconds — accurate because it came from the file that works rather than from someone's memory of it.

Auditing a container image

Docker Compose resolves environment variables from several places at once, with a precedence order that surprises people. Reading each source as JSON makes it obvious which one is actually winning.

What this handles that a split on "=" does not

  • Splits on the first equals sign only, so connection strings and query parameters survive.
  • Strips an export prefix, which is legal in a file meant to be sourced by a shell and appears in plenty of real ones.
  • Expands \n, \t and \" inside double-quoted values, and leaves them alone inside single-quoted ones.
  • Treats # as a comment only when it is outside quotes and follows whitespace — so pass#word stays a password.
  • Keeps an empty value as an empty string rather than dropping the key, because FEATURE_FLAG= is a decision someone made.
  • Names every key that is defined twice. Loaders take the last one silently; a duplicate in a committed file is nearly always a merge accident.
  • Reports malformed lines with their original line numbers instead of failing the whole file.
  • Strips a UTF-8 byte order mark, which a file saved from Notepad carries and which would otherwise become part of your first key name.

Questions people actually ask

Why are numbers and booleans still strings?

Because that is what they are. The environment is a string-to-string map at the operating-system level, and PORT=5432 reaches your process as text no matter what. Converting it here would be inventing a type the file never had — and it is exactly how ENABLE_CACHE=false becomes the truthy string "false" in code that forgot to parse it. If you want typed output, do the conversion deliberately in your own code where the intent is visible.

Is my .env sent anywhere?

No. The parsing runs in your browser and there is no upload step. That is deliberate for this page in particular — the file usually holds database passwords and API keys. If you still want to be careful, the Mask values toggle keeps the key names and replaces every value.

What happens to comments?

They are dropped, because JSON has nowhere to put them — the format has no comment syntax at all, which is the single most common complaint about using it for configuration. If the comments matter, keep the original file; this output is for reading and comparing, not for replacing it.

Does it handle multi-line values?

A value wrapped in double quotes with \n escapes converts correctly, and that is how a private key is normally stored in a single-line .env. A value that spans several actual lines in the file is not supported here, mostly because loaders disagree about whether it should be — python-dotenv accepts it and several Node loaders do not, so a file relying on it is already fragile.

Should configuration live in .env at all?

For local development, yes — it is the least friction. For deployed services the twelve-factor guidance on config makes the case for environment variables set by the platform rather than a file on disk, and for secrets specifically a managed store beats a file that can be committed by accident. A .env in a repository is one git add . away from being public.

Can I go the other way?

Yes — JSON to .env takes a JSON object and writes the file, quoting each value only where it needs quoting.

Related tools

Further reading

  • dotenv – The Node loader most .env conventions come from — its README is the closest thing the format has to a specification.
  • The Twelve-Factor App: Config – The argument for keeping configuration out of the code, and why it is stated in terms of environment variables.