Back

Environment variable converter

Developer tools

Loading

Loading tool

Preparing the tool. The remaining time is not yet known.

All processing for this tool happens in your browser. Your input is not sent to a server.

About this tool

Keep the original .env ↔ JSON converter, or compare a before and an after environment file locally. Comparison separates added, removed, changed, unchanged and ambiguous keys, including missing, empty and whitespace-only values. Values start hidden; generate a placeholder-only .env.example or deliberately opt into a JSON report containing values.

Common uses

  • Find renamed or missing deployment settings by comparing two supplied .env texts without contacting a server. A rename appears as one removed and one added key.
  • Prepare an onboarding .env.example from valid, unambiguous variable names while removing all original values and comments.
  • Continue converting .env assignments to JSON strings or JSON object properties to .env text; review quoting and type conversion before reuse.

How to use it

  1. 1.Choose .env → JSON or JSON → .env for the existing converter, or switch to comparison and paste the before and after texts. Empty comparison text represents no variables; the converter requires nonempty input.
  2. 2.Compare, inspect source line diagnostics, and review the five status counts. Filter or page the result; hidden values still distinguish missing, empty, whitespace and nonempty states. Resolve invalid lines before comparing and duplicate keys before treating them as a single value.
  3. 3.Choose before, after or union names for .env.example and review the names before copying or downloading. JSON export is masked by default; revealing values and including them in the report require explicit choices. Input edits invalidate results and reset value exposure.

Executable conversion and comparison examples

Convert environment assignments to JSON strings

APP_NAME=EveryTools
DEBUG=true
export API_URL="https://example.test"
{
  "APP_NAME": "EveryTools",
  "DEBUG": "true",
  "API_URL": "https://example.test"
}

Select .env → JSON. All three values remain strings, including true. The optional export prefix is removed; the converter never loads these variables into the browser or a process environment.

Convert JSON values with deliberate stringification

{"APP_NAME":"EveryTools","EMPTY":"","FLAGS":["a","b"],"DEBUG":true}
APP_NAME=EveryTools
EMPTY=""
FLAGS="[\"a\",\"b\"]"
DEBUG=true

Select JSON → .env. The empty string stays explicit, the boolean becomes text, and the array becomes a quoted JSON string. This does not preserve the original JSON value types on a later .env → JSON conversion.

Review all four unambiguous comparison statuses

before:
APP=demo
PORT=3000
OLD=retire

after:
APP=demo
PORT=4000
NEW=added
[{"key":"APP","status":"unchanged","before":"value","after":"value"},{"key":"NEW","status":"added","before":"missing","after":"value"},{"key":"OLD","status":"removed","before":"value","after":"missing"},{"key":"PORT","status":"changed","before":"value","after":"value"}]

Paste the before and after sections into their respective comparison inputs. Output below is a compact key/status/state summary, sorted by key, rather than the complete downloadable report. PORT changes while APP remains unchanged.

Distinguish missing, empty and whitespace-only values

before:
EMPTY=
SPACE=" "
GONE=

after:
EMPTY=""
SPACE=
ADDED=" "
[{"key":"ADDED","status":"added","before":"missing","after":"whitespace"},{"key":"EMPTY","status":"unchanged","before":"empty","after":"empty"},{"key":"GONE","status":"removed","before":"empty","after":"missing"},{"key":"SPACE","status":"changed","before":"whitespace","after":"empty"}]

The summary exposes value state without exposing values. Missing, empty and whitespace-only are three different states. EMPTY keeps an empty decoded string despite different quoting, while SPACE changes from one space to empty.

Compare decoded quotes, comments and literal references

before:
export HASH="a#b" # comment
LINE="a\nb"
REF=${HOME}
COMMAND="$(whoami)"
PATH='C:\temp'

after:
HASH=a#b
LINE="a\u000ab"
REF='${HOME}'
COMMAND='$(whoami)'
PATH="C:\\temp"
[{"key":"COMMAND","status":"unchanged","before":"value","after":"value"},{"key":"HASH","status":"unchanged","before":"value","after":"value"},{"key":"LINE","status":"unchanged","before":"value","after":"value"},{"key":"PATH","status":"unchanged","before":"value","after":"value"},{"key":"REF","status":"unchanged","before":"value","after":"value"}]

These inputs decode to the same values. JSON \n and \u000a encode the same newline inside a single source line. The reference and command-looking text remain literal; nothing is expanded, executed or fetched.

Keep duplicate assignments explicitly ambiguous

before:
TOKEN=first
TOKEN=second
SAME=demo

after:
TOKEN=second
SAME=demo
[{"key":"SAME","status":"unchanged","before":"value","after":"value"},{"key":"TOKEN","status":"ambiguous","before":"ambiguous","after":"value"}]

TOKEN is ambiguous because it appears on before lines 1 and 2. Matching the last occurrence to the after value would hide the conflict, so the tool does not choose one. SAME can still be compared normally.

Generate a union example with fixed placeholders

before:
__proto__=synthetic-before
constructor=synthetic-constructor
OLD=retired
# internal comment
DUP=first
DUP=second

after:
__proto__=synthetic-after
constructor=synthetic-constructor
NEW=synthetic-added
DUP=only
NEW=REPLACE_ME
OLD=REPLACE_ME
__proto__=REPLACE_ME
constructor=REPLACE_ME

Choose union when generating .env.example. Both special JavaScript property names are valid ASCII variable names. DUP is excluded because the before side contains duplicates; original values and the comment are never included. Every emitted name receives the fixed REPLACE_ME placeholder.

Block a comparison containing an invalid variable name

before:
GOOD=ok
BAD-NAME=synthetic

after:
GOOD=ok
{"valid":false,"rows":[],"beforeIssues":[{"code":"invalidKey","line":2}],"afterIssues":[]}

BAD-NAME violates the ASCII key grammar on before line 2. The compact diagnostic summary shows no comparison rows, so GOOD is not misleadingly reported as unchanged. Fix the source first; JSON diff and .env.example exports remain blocked.

Common .env mistakes and disclosure risks

  • Treating an unquoted # after a space as part of a value: quote values that intentionally contain such text.
  • Pasting a shell script or a multiline secret: this comparison parser accepts only its documented single-line subset and never executes it.
  • Assuming duplicate keys use the last value: ambiguous keys require review even when the repeated values look identical.
  • Sharing a raw-value report or screen after revealing values: it may disclose credentials; key names in masked reports and examples can also be sensitive.
  • Using REPLACE_ME as a production default: generated examples list names for review and contain no usable configuration values.

Limits and notes

  • Comparison uses a documented custom single-line subset, not full dotenv or shell compatibility. Keys are case-sensitive ASCII [A-Za-z_][A-Za-z0-9_]*, including __proto__ and constructor. An initial BOM, LF/CRLF, optional export and ASCII space/tab around assignments are supported. Double quotes use JSON escapes; single quotes decode only escaped quotes and escaped backslashes, keeping other backslashes literal. Quoted spaces are preserved. Bare values trim ASCII space/tab; # begins a comment at value start or after space/tab, while a#b remains literal. A quoted value may be followed only by space/tab and a comment.
  • Multiline values, bare CR, raw control characters other than horizontal tab, Unicode line separators, invalid names, unfinished quotes and ambiguous bare shell syntax are rejected. Bare embedded quotes, backticks, backslashes and ; | & < > require supported quoting. ${HOME} and $(whoami) are data only: no variable expansion, command substitution or evaluation occurs.
  • Any malformed line blocks the whole comparison and both report/template exports, rather than treating ignored lines as removed keys. Duplicate keys remain visible as ambiguous with source lines and no selected value; there is no last-wins rule. Union examples omit a key duplicated on either side; side-specific examples require it to be unique on the selected side.
  • Each comparison input is limited to 200,000 UTF-16 code units and 5,000 physical lines; exports are limited to 1 MB (1,000,000 UTF-8 bytes). A final line terminator does not add an extra physical line. Limits fail explicitly without truncated exports. The retained converter accepts 200,000 characters and at most 5,000 lines or JSON properties, with its own conversion rules.
  • Processing stays in the browser with no input upload, network lookup or persistent storage. Hiding values is a display/export choice, not encryption. Raw-value JSON may expose secrets; even masked reports and .env.example reveal key names and structure. Example values are always REPLACE_ME, never guessed defaults; original values, comments and invalid lines are never copied.

Frequently asked questions

How is a missing variable different from an empty value?

A missing key has no assignment. KEY= and KEY="" both represent an empty string. KEY=" " is whitespace-only and differs from empty; unquoted surrounding spaces are trimmed. Comparison uses decoded strings without boolean, numeric or case normalization.

What happens when the same key occurs twice?

Both source line numbers remain available. Even identical duplicate values produce ambiguous status, not unchanged or a last-wins result. Resolve the duplicate before using the value; the union .env.example excludes that name.

Does a masked JSON report contain the original values?

The default report omits value properties and raw input lines while retaining keys, states, line numbers, statuses and counts. An explicit include-values choice adds parsed values and can disclose secrets. Revealing the table does not itself grant permission to export values.

Can I still convert existing .env and JSON data?

Yes. Choose either original conversion direction. .env → JSON returns string values and rejects duplicate keys; JSON → .env stringifies booleans/numbers, uses an empty value for null and serializes arrays/objects as JSON text. This converter keeps its earlier quoting/comment behavior; comparison applies the stricter custom subset described above.

Related tools