Skip to content
LocalOnly

JSON Merge

Stable

Deep-merge two or more JSON objects into one.

Everything is processed locally in your browser

About JSON Merge

The JSON Merge tool combines multiple JSON objects into a single document using a configurable deep-merge. Nested objects are merged recursively, and you control how conflicts and arrays are resolved so the result matches your intent. It is the reliable way to layer defaults with overrides or combine partial configs.

Features

  • Recursive deep merge of nested objects
  • Later sources override earlier ones for conflicting keys
  • Choose array strategy: replace, concatenate, or merge by index
  • Merge two or more documents in a single operation
  • Predictable, order-dependent conflict resolution
  • Validates each source before merging

How to use JSON Merge

  1. 1

    Add your JSON sources

    Provide two or more JSON objects, ordered from base to highest priority.

  2. 2

    Pick an array strategy

    Decide whether arrays should be replaced, concatenated, or merged by index.

  3. 3

    Merge

    The tool deep-merges the sources, with later objects overriding earlier ones on conflicts.

  4. 4

    Copy the merged JSON

    Use the combined document as your final config or payload.

Examples

Deep merge with override

The second object overrides theme and adds a key.

Input

// base
{ "theme": "light", "layout": { "sidebar": true } }

// override
{ "theme": "dark", "layout": { "compact": true } }

Output

{
  "theme": "dark",
  "layout": {
    "sidebar": true,
    "compact": true
  }
}

How merging JSON works

Shallow and deep merging give different answers

A shallow merge copies top-level keys from one document over another. If both documents have a `database` object, the second one replaces the first entirely - every nested key inside the original is lost, including keys the second document never mentioned. This is what JavaScript's object spread and `Object.assign` do, and it surprises people constantly.

A deep merge recurses. When both sides have an object at the same key, it merges those objects too, and keeps descending. Keys present in only one side survive. `{"db":{"host":"a","port":1}}` merged over `{"db":{"host":"b"}}` yields `{"db":{"host":"b","port":1}}` - the port survives, which is almost always what you wanted.

For layered configuration, deep merging is essentially always the correct choice. A production override that specifies only `database.host` should not silently discard the pool size, timeout and credentials that the base layer defined.

Arrays have no obviously right answer

Objects merge by key, which is well-defined. Arrays do not have keys, so the merge has to choose a policy, and each policy is correct for some data and wrong for other data.

Replacing the array wholesale is the most predictable and is what RFC 7396 JSON Merge Patch specifies. Concatenating appends the second array to the first, which suits event lists but duplicates entries when the same merge runs twice. Merging by index pairs element 0 with element 0 and so on, which works for fixed-length records and produces nonsense for lists that grow. Merging by identity - pairing elements that share an `id` field - is usually what people actually want for collections, and it requires knowing which field is the identifier.

The practical guidance is to replace by default, and to reach for something smarter only when you can say precisely which elements correspond and why.

How this relates to JSON Merge Patch and JSON Patch

Two standards cover this ground and they are frequently confused. JSON Merge Patch (RFC 7396) is a deep merge where `null` means delete the key. It is compact and readable, and its limitation is that you cannot set a field to null, because null is reserved as the delete signal. Arrays are always replaced entirely.

JSON Patch (RFC 6902) is a different shape: an explicit array of operations - add, remove, replace, move, copy, test - each with a JSON Pointer path. It is more verbose but can express array insertions at a specific index, and it can set a field to null. It also supports `test`, which enables optimistic concurrency.

If you are designing a PATCH endpoint, Merge Patch is the friendlier choice for whole-object updates, and JSON Patch is the one you need for precise array manipulation.

Reference

Array merge strategies compared

Strategy[1,2] over [3,4] givesRight for
Replace[3,4]Config overrides; the RFC 7396 default
Concatenate[1,2,3,4]Event and log accumulation
By index[3,4]Fixed-length positional records
By identityDepends on idsCollections of objects with stable keys

Which tool should you use?

These tasks overlap. Here is how to pick the right one for what you are actually doing.

You are layering environment config over a base file
Deep merge with array replacement. This is the standard configuration pattern.
You want to know what differs rather than combine
The JSON Compare tool is the right one - merging hides differences by resolving them.
You need to insert into an array at a specific position
No merge strategy expresses that. Use JSON Patch (RFC 6902), which has explicit array operations.
You need to delete keys as part of the merge
JSON Merge Patch semantics use `null` for deletion. Keep those nulls - do not run a null-stripping tool over the patch.

Use cases

  • Layering environment overrides on top of a base configuration
  • Combining default settings with user-specified options
  • Merging partial API responses into a single object
  • Assembling a config from several fragment files
  • Applying a patch object to an existing document

Troubleshooting common errors

Nested keys vanished from the result

Why: A shallow merge replaced an entire nested object rather than merging into it.

Fix: Use a deep merge. This is the difference between `Object.assign` and a recursive merge, and it is the most common merge bug.

Array elements were replaced when you expected them combined

Why: Replacement is the default, and it is what RFC 7396 specifies.

Fix: Concatenate or merge by identity if that suits your data - but be explicit about it, because each strategy is wrong for some inputs.

Running the same merge twice produced duplicate array entries

Why: Concatenation is not idempotent - each run appends again.

Fix: Merge by identity, or deduplicate afterwards. For any merge that may be retried, idempotency is worth designing for.

A key you wanted set to null was deleted instead

Why: Under JSON Merge Patch semantics, `null` is the delete instruction.

Fix: Use JSON Patch (RFC 6902), which can set a value to null explicitly. This is a genuine expressiveness gap in Merge Patch.

Limitations

What this tool deliberately does not do, so you know when to reach for something else.

  • Array merging has no universally correct strategy; whichever you pick will be wrong for some data.
  • Under merge-patch semantics you cannot set a field to null, because null means delete.
  • Type conflicts resolve by overwrite - a merge cannot reconcile a string with an object.
  • Concatenation is not idempotent, so repeated merges accumulate duplicates.
  • Merging cannot insert at a specific array index; that needs JSON Patch.

Frequently asked questions

Learn more

Command Palette

Search for a tool or command