JSON Deep Merge

Recursively merge two JSON objects with configurable array and conflict strategies.

{
  "name": "Annabel",
  "address": {
    "city": "NYC",
    "zip": "10002",
    "country": "US"
  },
  "tags": [
    "b",
    "c"
  ],
  "meta": {
    "active": true,
    "verified": true
  }
}

About JSON Deep Merge

JSON Deep Merge recursively merges two JSON objects: keys present in only one input pass through unchanged; keys present in both are merged according to your strategy. For nested objects the merge recurses; for primitives, the second input wins by default; for arrays, you choose between concat (append), union (concat then dedupe), or overwrite (B replaces A entirely).

This is the canonical layered-config operation. Build a runtime config from `default.json` and `production.json`; combine a base API request body with per-call overrides; collapse a feature-flag default with a tenant-specific override. It works on objects, not on arrays of records — for that use case, use JSON Array Merger, which performs a SQL-style join on a chosen key. Deep Merge is order-sensitive: A then B is not the same as B then A whenever the same key holds different primitive values.

Examples

Input
A: {"server":{"host":"localhost","port":80}}
B: {"server":{"port":443,"ssl":true}}
Output
{"server":{"host":"localhost","port":443,"ssl":true}}

Conflict strategy: B wins for primitives. Both `host` and `ssl` survive because they appear in only one side.

Frequently asked questions

How is this different from JSON Array Merger?

Deep Merge merges objects by key. Array Merger merges arrays of objects on a join key (inner / left / right / outer). Use Deep Merge for layered configs; use Array Merger for SQL-style joins on records.

What is the default array strategy?

Concat — append B to A. Switch to union if you want concat-then-dedupe, or overwrite if B's array should replace A's entirely. Pick the strategy that matches the meaning of your data.

Is the merge associative?

Yes when the conflict strategy is 'B wins': merge(merge(A, B), C) equals merge(A, merge(B, C)) for any A, B, C. With the array union strategy the operation is still well-defined but order can affect the result for repeated values.

What if one input is null and the other is an object?

Null is treated as a primitive value. With the default 'B wins' strategy, whichever side comes second prevails — so merging `{a:1}` with `null` returns `null`, and merging `null` with `{a:1}` returns `{a:1}`. Switch to 'A wins' if your null represents 'no override'.