# JSON Merge Patch The library supports JSON Merge Patch ([RFC 7396](https://tools.ietf.org/html/rfc7396)) as a patch format. The merge patch format is primarily intended for use with the HTTP PATCH method as a means of describing a set of modifications to a target resource's content. Applying a merge patch changes the JSON value the patch is applied to. Instead of using [JSON Pointer](json_pointer.md) to specify values to be manipulated, it describes the changes using a syntax that closely mimics the document being modified. Unlike [JSON Patch](json_patch.md), a JSON Merge Patch cannot express every kind of change (e.g., it cannot reorder array elements or remove a specific array element), but it is easier to read and write for object-shaped documents. The function [`merge_diff`](../api/basic_json/merge_diff.md) creates a merge patch that changes one JSON value into another. The example below applies one patch to one document. Here is the document before: ```json { "title": "Goodbye!", "author": { "givenName": "John", "familyName": "Doe" }, "tags": ["example", "sample"], "content": "This will be unchanged" } ``` This is the patch: ```json { "title": "Hello!", "phoneNumber": "+01-123-456-7890", "author": { "familyName": null }, "tags": ["example"] } ``` And this is the document after applying it: ```json { "title": "Hello!", "author": { "givenName": "John" }, "tags": ["example"], "content": "This will be unchanged", "phoneNumber": "+01-123-456-7890" } ``` The table goes through the members one by one. "Member" is the name of an object member in the patch (and in the document); it is not a [JSON Pointer](json_pointer.md) and nothing of it is passed to the function: the whole patch is passed to [`merge_patch`](../api/basic_json/merge_patch.md).
| Rule | Member | Before | Patch | After | |------|--------|--------|-------|-------| | change value | `title` | `#!json "Goodbye!"` | `#!json "Hello!"` | `#!json "Hello!"` | | add key | `phoneNumber` | (no member) | `#!json "+01-123-456-7890"` | `#!json "+01-123-456-7890"` | | object merges recursively | `author` | `#!json {"givenName": "John", "familyName": "Doe"}` | `#!json {"familyName": null}` | `#!json {"givenName": "John"}` | | null removes key | `familyName` inside `author` | `#!json "Doe"` | `#!json null` | (removed) | | array replaced whole | `tags` | `#!json ["example", "sample"]` | `#!json ["example"]` | `#!json ["example"]` | | unchanged key | `content` | `#!json "This will be unchanged"` | (no member) | `#!json "This will be unchanged"` |
An array in the patch replaces the array in the target, so a merge patch cannot change a single element. Each member of the patch is applied like this; a patch that is not an object replaces the whole target. ```mermaid flowchart LR M["member of the patch"] --> N{{"value null?"}} N -->|yes| D["delete the key"] N -->|no| O{{"value an object?"}} O -->|yes| R["merge recursively into the target's value"] O -->|no| S["set the key to the value"] ```

How one member of a merge patch is applied: a `null` value deletes the key, an object is merged recursively, and any other value replaces the value of the key.

!!! tip "Not a general deep merge" A merge patch is not a general deep merge: a `#!json null` value in the patch deletes the key from the target. To merge two objects recursively (e.g., defaults and user settings), use [`update`](../api/basic_json/update.md) with `merge_objects` set to `#!cpp true`; see [Merging objects](modifying_values.md#merging-objects). !!! note "Limitations of RFC 7396" - A patch cannot set a member to `#!json null`, because `#!json null` removes the member: `#!json {"a":1}` patched with `#!json {"a":null}` gives `#!json {}`. - Arrays are replaced as a whole, never merged, and a `#!json null` inside an array is kept. - `#!json null` members of the target that the patch does not mention are preserved. - A `#!json null` that would remove a member of a not yet existing object still creates that object: `#!json {}` patched with `#!json {"a":{"b":null}}` gives `#!json {"a":{}}`. - A patch that is not an object replaces the whole target (a `#!json null` patch makes the target `#!json null`); an object patch applied to a non-object target starts from an empty object. - [`merge_diff`](../api/basic_json/merge_diff.md#notes) has a matching limitation for `#!json null` members. ??? example The following code shows how a JSON Merge Patch is applied to a JSON document. ```cpp #include #include #include // for std::setw using nlohmann::json; using namespace nlohmann::literals; int main() { // the original document json document = R"({ "title": "Goodbye!", "author": { "givenName": "John", "familyName": "Doe" }, "tags": [ "example", "sample" ], "content": "This will be unchanged" })"_json; // the patch json patch = R"({ "title": "Hello!", "phoneNumber": "+01-123-456-7890", "author": { "familyName": null }, "tags": [ "example" ] })"_json; // apply the patch document.merge_patch(patch); // output original and patched document std::cout << std::setw(4) << document << '\n'; } ``` Output: ```json { "author": { "givenName": "John" }, "content": "This will be unchanged", "phoneNumber": "+01-123-456-7890", "tags": [ "example" ], "title": "Hello!" } ``` ## See also - [JSON Patch and Diff](json_patch.md) - a more expressive alternative that describes a sequence of operations - [JSON Pointer](json_pointer.md) - the addressing scheme used by JSON Patch - [`merge_patch`](../api/basic_json/merge_patch.md) - apply a JSON Merge Patch to a value - [`merge_diff`](../api/basic_json/merge_diff.md) - create a JSON Merge Patch from two values - Function [`update`](../api/basic_json/update.md) - merge objects, optionally recursively - [Modifying values](modifying_values.md) - simple in-place modifications