How to merge user settings json with application defaults
- Step 1Paste application defaults into JSON Input 1 — Input 1 is the complete defaults object — every setting with its default value. It must be a single valid JSON object. This is the fallback layer the user override folds into.
- Step 2Paste the user override into JSON Input 2 — Input 2 is the sparse user settings — only the keys the user changed. Last-wins means each key here overrides the matching default; keys the user didn't set fall through to the default.
- Step 3Add more layers if needed with Add input — For org-default → team-default → user precedence, click Add input to add layers. Order is precedence: most-authoritative (the individual user) last. Free tier merges 2 inputs; Pro up to 10.
- Step 4Keep Deep merge selected — Deep merge (default) folds nested settings sections recursively so a user who changed one leaf keeps every sibling default. Use First wins if defaults must be authoritative and the user can only add new keys, or Array append if list settings should accumulate.
- Step 5Click Merge Objects — Both inputs are parsed and folded defaults-then-user. If either isn't valid JSON the merge stops with the parser message. At least 2 non-empty inputs are required.
- Step 6Verify the effective settings, then export — Confirm the user's customisations won and the untouched defaults survived. Copy or Download (
merged.json). To see exactly which settings the user changed, diff defaults against the merged output with the json-diff.
Strategy behaviour for settings merges
How each strategy resolves a defaults-vs-user collision. 'Section' = both sides are nested settings objects; 'List' = both are arrays; 'Scalar' = string/number/boolean/null or mismatched types. Defaults are Input 1; the user override (Input 2) is 'later'.
| Strategy | Settings section (object) | List value (array) | Scalar value | When to use |
|---|---|---|---|---|
| Deep merge (default) | Recursively merged | User list replaces default | User wins | standard defaults + user override |
| Shallow | User replaces whole section | User list replaces default | User wins | flat single-level prefs |
| First wins | Default kept (user ignored) | Default list kept | Default kept | managed/locked defaults; user adds only |
| Array append | User replaces whole section | default ++ user | User wins | lists that accumulate (extensions, plugins) |
Defaults + user override resolution
How individual settings resolve under deep merge when the user override is sparse.
| Setting | Default | User override | Effective |
|---|---|---|---|
editor.fontSize | 14 | 16 | 16 (user) |
editor.tabSize | 2 | (absent) | 2 (default) |
theme | light | dark | dark (user) |
telemetry.enabled | true | (absent) | true (default) |
extensions | ["core"] | ["vim"] | ["vim"] (deep) / ["core","vim"] (append) |
Cookbook
Real defaults/user-override pairs from settings resolution, showing what each strategy produces. All runs are client-side.
Sparse user override keeps untouched defaults
ExampleThe user changed only the font size and theme. Deep merge applies those while keeping tabSize, wordWrap, and every other default intact — exactly how an app computes effective settings.
Input 1 (defaults.json):
{ "editor": { "fontSize": 14, "tabSize": 2, "wordWrap": "off" },
"theme": "light", "telemetry": { "enabled": true } }
Input 2 (user.json):
{ "editor": { "fontSize": 16 }, "theme": "dark" }
Strategy: Deep merge
Output (effective settings):
{
"editor": { "fontSize": 16, "tabSize": 2, "wordWrap": "off" },
"theme": "dark",
"telemetry": { "enabled": true }
}Shallow drops the defaults the user didn't restate
ExampleSame inputs, Shallow strategy. Shallow replaces the entire editor object with the user's, so tabSize and wordWrap vanish. This is the bug deep merge prevents for settings.
Input 1: { "editor": { "fontSize": 14, "tabSize": 2, "wordWrap": "off" } }
Input 2: { "editor": { "fontSize": 16 } }
Strategy: Shallow
Output:
{ "editor": { "fontSize": 16 } }
→ tabSize and wordWrap GONE. Use Deep merge.Managed defaults: user can add but not override
ExampleAn org wants its defaults to be authoritative — users may add personal keys but cannot override managed ones. First wins keeps every default and only accepts new keys from the user.
Input 1 (managed defaults): { "telemetry": { "enabled": true } }
Input 2 (user): { "telemetry": { "enabled": false }, "theme": "dark" }
Strategy: First wins
Output:
{
"telemetry": { "enabled": true },
"theme": "dark"
}
→ telemetry NOT disabled by user; theme added.Accumulate an extensions/plugins list
ExampleDefault extensions plus the user's should both be active. Deep merge would replace the default list with the user's; Array append combines them.
Input 1 (defaults): { "extensions": ["core", "git"] }
Input 2 (user): { "extensions": ["vim"] }
Strategy: Deep merge → { "extensions": ["vim"] }
Strategy: Array append → { "extensions": ["core", "git", "vim"] }Org → team → user precedence (three layers)
ExampleLayer org defaults, then team overrides, then the individual user — least specific first, user last. Requires Pro for three inputs (or two passes on free).
Input 1 (org): { "theme": "light", "editor": { "tabSize": 4 } }
Input 2 (team): { "editor": { "tabSize": 2 } }
Input 3 (user): { "theme": "dark" }
Strategy: Deep merge
Output:
{
"theme": "dark",
"editor": { "tabSize": 2 }
}
→ tabSize from team, theme from user.Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
User override replaces a list-valued setting
By designUnder deep merge, a user's array (e.g. extensions, recentFiles) replaces the default array entirely rather than merging. If you intended the default and user lists to combine, switch to Array append. Always check array-valued settings after merging so you don't silently drop default list entries.
Settings file isn't valid JSON
Parse errorVS Code settings.json permits // comments and trailing commas (it's JSONC), but this tool's parser is strict JSON and rejects them. Strip comments and trailing commas first, or run the file through the json-format-fixer before merging.
User sets a section to null to 'reset' it
Last winsA user override of { "editor": null } replaces the whole default editor object with null (object-vs-null type mismatch under last-wins) — it does not restore defaults. To drop null-valued keys from the effective settings, run the json-null-stripper afterward.
More than 2 settings layers on free tier
Upgrade requiredorg → team → user is three inputs, which exceeds the free 2-input limit. Pro allows up to 10. On free, merge org + team, copy the result back into Input 1, then add the user override as Input 2 for a second pass.
Settings stored as flat dotted keys
Flat keysVS Code uses flat dotted keys ("editor.fontSize": 16) rather than nested objects. Deep merge treats "editor.fontSize" as one literal key, which still merges correctly key-for-key — but it won't fold a dotted-key override into a nested-object default (or vice versa). Keep both inputs in the same shape, or use the json-unflattener to normalise.
User override value type differs from the default
Last winsIf the default is "fontSize": 14 (number) and the user has "fontSize": "16" (string), the string replaces the number — types aren't coerced. A settings loader expecting a number may then misbehave. Normalise value types in the user override to match the defaults before merging.
Empty user settings file
RejectedIf the user has changed nothing, their settings file may be empty or {}. An empty textarea is ignored (dropping you below the 2-input minimum); an explicit {} is valid but merges to just the defaults. If you only want to pretty-print or validate the defaults alone, use the json-prettifier instead.
Tokens or secrets stored in settings
PreservedAPI tokens or credentials kept in a settings blob are merged as plain values and appear verbatim in the output. Nothing is uploaded (the merge is in-browser), but if you plan to share the effective settings, redact sensitive values first with the json-anonymizer.
Frequently asked questions
How do I compute a user's effective settings?
Put the complete application defaults in Input 1 and the user's sparse override in Input 2, then run Deep merge. The user wins any key they set; every key they didn't set falls through to the default. The merged output is the effective settings the app would resolve at runtime.
Why does deep merge matter for settings?
User settings are usually sparse — they store only changed keys. With a nested structure like { "editor": { "fontSize", "tabSize" } }, a user who changed only fontSize must keep the default tabSize. Deep merge folds the override into the defaults key-by-key so siblings survive; a shallow spread would replace the whole editor object and lose the defaults.
Which value wins — default or user?
With defaults in Input 1 and the user override in Input 2, the user wins because inputs merge left-to-right with last-wins. If you instead want defaults to be authoritative (user can add keys but not override managed ones), use the First wins strategy with defaults first.
Do unspecified settings fall back to defaults?
Yes — that's the whole point of deep merge here. Any key the user didn't include simply retains the default value from Input 1. Only keys the user explicitly set are overridden, and even then only at the specific leaf they changed, thanks to recursive folding.
Can I enforce managed defaults the user can't override?
Use the First wins strategy with the managed defaults in Input 1. First wins keeps every key already defined (the managed defaults) and only accepts keys the user introduces that don't already exist — so a user can add personal preferences but can't flip a locked default.
How do I combine default and user list settings?
Use Array append. By default (deep merge) the user's array replaces the default array; array-append concatenates them, which is what you want for things like an extensions or enabled-plugins list where both the defaults and the user's choices should be active.
Does this handle VS Code settings.json directly?
Mostly — but VS Code uses JSONC (comments and trailing commas allowed) and flat dotted keys. Strip comments and trailing commas first (or use the json-format-fixer), and keep both inputs in the same key shape. Flat dotted keys merge fine against each other; just don't mix dotted-key and nested-object inputs in one merge.
Are user preferences uploaded anywhere?
No. The merge runs entirely in your browser. A user's preferences, workspace paths, and any tokens stored in settings are processed in-tab and never sent to a server. Only an anonymous run count is recorded for signed-in dashboard stats.
How do I see which settings a user customised?
Merge defaults + user here, copy the effective settings, then diff the defaults against the merged result with the json-diff. The diff lists exactly which keys differ from the defaults — a clean report of everything the user changed.
Can I merge org, team, and user layers together?
On Pro, yes — up to 10 inputs, ordered least-specific (org) first to most-specific (user) last. On the free tier you can do two at a time: merge org + team, copy the result back as the base, then add the user override for a second pass.
Can I change the output indentation?
The web tool outputs 2-space indentation only. To re-format the effective settings (4-space, tabs) or compact them, run the result through the json-prettifier or json-minifier.
Can I automate effective-settings resolution?
Yes — the merger runs as a runner-local tool on Pro, keeping user data on your machine, with the same deep/first-wins/array-append strategies. A backend job can fold defaults + per-user overrides to materialise effective settings, and validate them with the json-validator.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.