Config Merge Tool
Paste up to four configuration layers — JSON, YAML, TOML or .env — and merge them from lowest to highest precedence. Choose deep or shallow object merging, list behaviour, null deletion, variable substitution and output as JSON, YAML, TOML, env or an annotated report. Runs locally in your browser.
About this tool
Real applications usually read more than one configuration file: a checked-in default, an
environment-specific override, a local file, and finally deployment variables. This tool merges
those layers in the same order. Paste JSON, YAML, TOML or .env text into the four layer boxes;
blank layers are skipped, and later layers override earlier layers.
The result is a normalized config document, not a textual patch. Comments, blank lines and YAML
anchors are not preserved because they are not part of the merged value tree. The upside is that
layers can use different formats: a JSON base, YAML staging override and .env deployment layer
can all merge into one JSON, YAML, TOML, .env or report output.
Worked example — JSON base, YAML override and env values
Layer 1:
{
"db": { "host": "localhost", "port": 5432 },
"debug": false
}
Layer 2:
db:
host: staging.internal
Layer 3:
DEBUG=true
DB__PORT=6543
With the defaults, the merged JSON is:
{
"db": {
"host": "staging.internal",
"port": "6543"
},
"debug": "true"
}
The YAML layer changed only db.host. The .env layer used DB__PORT to address db.port and
DEBUG to override debug using the default case-matching mode. Env values are strings, so the
port and debug values are strings in the result.
Merge options
- Object merge: deep merge nested objects, or shallow-replace the whole top-level value.
- Array merge: replace lists (default), append lists, or append only values that are not already present.
- Null deletes: with the default on, a later
nullremoves an inherited key; turn it off to keepnullas a value. - Key case matching: default
matchlets env-styleDB__HOSToverridedb.host;preservetreats case differences as separate keys. - Variable substitution:
${VAR},${VAR:-default}and${VAR-default}expand after the merge. Values come from the Vars box first, then from the merged config itself (${db.host}or${DB__HOST}).$$is a literal dollar sign, and unresolvable references are left as written.
Limits and edge cases
- Total pasted input is capped at 256 KiB across all layers and vars.
- Nesting is capped at 64 levels.
- Each layer must parse to a top-level mapping/object. Bare lists and scalars are rejected.
- TOML output cannot represent
null, so nulls are dropped before TOML serialization. .envoutput flattens nested paths with__and uppercases them. It rejects lists of objects and key collisions such asdb.hostplusdb__hostbecoming the same env name.- Auto-detection is intentionally simple: valid JSON wins first,
[section]means TOML,KEY=valuewithout spaces means.env, TOML-stylekey = valueis TOML when it parses, and the remaining mapping syntax is YAML. Force the input format when your file is ambiguous.
FAQ
Which layer wins when two layers set the same key?
Layers apply left to right. Layer 1 is the base, layer 2 overrides it, layer 3 overrides both, and layer 4 has the highest precedence. Use Output format → Annotated report when you need to see which layer set each final value and which keys were overridden.
Can I merge JSON, YAML, TOML and .env in one run?
Yes. With Input format → Auto-detect each layer, every non-blank layer is sniffed independently
and converted into the same internal value tree before merging. That means a JSON base can be
overridden by YAML and then by .env variables. If a layer is ambiguous, choose a forced input
format so every layer is parsed the same way.
Why did my env override change a number into a string?
.env files are text, so PORT=6543 is parsed as the string "6543". JSON, YAML and TOML layers
keep their typed booleans and numbers. If you need a typed numeric override, use a JSON, YAML or
TOML layer instead of .env, or post-process the merged output with a schema-aware validator.
How do I remove a default from a later layer?
Leave Null deletes inherited keys on and set the key to null in the later JSON or YAML layer.
For example, cache: { ttl: null } removes an inherited cache.ttl. Turn the option off when you
want null to survive as an explicit value in JSON or YAML output.
Does variable substitution read my real environment?
No. The tool does not read browser, shell or deployment environment variables. It only uses values you paste into the Vars box and values already present in the merged config tree. That makes the run reproducible and keeps secrets out of the output unless you explicitly reference them.
Developer & Automation Access
Run it from the terminal
Same engine as this page, headless — via the gizza CLI:
gizza tool config-merge '{
"db": { "host": "localhost", "port": 5432 },
"debug": false
}'New to the CLI? Get gizza →
Open it by URL
Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:
https://gizza.ai/tools/config-merge/?layer1=%7B%0A%20%20%22db%22%3A%20%7B%20%22host%22%3A%20%22localhost%22%2C%20%22port%22%3A%205432%20%7D%2C%0A%20%20%22debug%22%3A%20false%0A%7D&layer2=db%3A%0A%20%20host%3A%20staging.internal&layer3=DEBUG%3Dtrue%0ADB__PORT%3D6543&layer4=debug%20%3D%20false&layer_names=defaults.json%2Cstaging.yaml%2C.env%2Clocal.toml&input_format=auto&output=json&object_merge=deep&array_merge=replace&key_case=match&null_deletes=true&substitute=true&vars=DB_USER%3Dsvc%0ADB_PASSWORD%3D%2A%2A%2A&sort_keys=true&indent=2Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.
