Files
json/api/basic_json/merge_patch.md
T
2026-10-27 12:14:00 +00:00

5.6 KiB

nlohmann::basic_json::merge_patch

void merge_patch(const basic_json& apply_patch);

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. This function applies a merge patch to the current JSON value.

The function implements the following algorithm from Section 2 of RFC 7396 (JSON Merge Patch):

define MergePatch(Target, Patch):
  if Patch is an Object:
    if Target is not an Object:
      Target = {} // Ignore the contents and set it to an empty Object
    for each Name/Value pair in Patch:
      if Value is null:
        if Name exists in Target:
          remove the Name/Value pair from Target
      else:
        Target[Name] = MergePatch(Target[Name], Value)
    return Target
  else:
    return Patch

Thereby, Target is the current object; that is, the patch is applied to the current value.

Parameters

apply_patch (in)
the patch to apply

Exception safety

Basic guarantee: if an exception is thrown during the operation, the JSON value may be partially modified.

Complexity

Linear in the total number of values (including nested ones) in apply_patch, times the cost of a key-based object operation (looking up, adding, or erasing a member): logarithmic for json, and linear for ordered_json (see ordered_map complexity). For ordered_json, patching an object that has n members with a patch that has m members therefore takes O(n·m). The cost also includes one copy of apply_patch (see the notes below).

Notes

  • apply_patch may be #!cpp *this itself or refer to a value contained in #!cpp *this (for example, a subobject returned by #!cpp (*this)[key]); it is read as it was when merge_patch() was called, before any modification of #!cpp *this. To make this possible, the function copies apply_patch before it modifies #!cpp *this, so the cost includes one copy of the patch.
  • A merge patch uses #!json null to remove a member, so it cannot set a member to #!json null: applying #!json {"a":null} to #!json {"a":1} gives #!json {}.
  • Arrays are not merged: an array in the patch replaces the target value as a whole, and a #!json null inside an array is kept as an element. #!json null members of the target that the patch does not mention are preserved.
  • A #!json null in the patch only removes a member; it does not prevent the creation of the enclosing objects. Applying #!json {"a":{"b":null}} to #!json {} gives #!json {"a":{}} (see example 15 in Appendix A of the RFC).
  • If apply_patch is not an object, it replaces the target as a whole. In particular, a #!json null patch turns the target into #!json null. If apply_patch is an object and the target is not, the target is first replaced by an empty object, so applying #!json {} to #!json 1 gives #!json {}.
  • A merge patch cannot express every change; for example, it cannot reorder array elements or remove a specific array element. Use JSON Patch (RFC 6902) for that. merge_diff has a matching limitation, see its notes.
  • A discarded value is treated like any other non-object value: a discarded apply_patch turns the target into a discarded value, and an object patch replaces a discarded target by an object as described above.

Examples

??? example

The following code shows how a JSON Merge Patch is applied to a JSON document.
 
```cpp
#include <iostream>
#include <nlohmann/json.hpp>
#include <iomanip> // 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

Version history

  • Added in version 3.1.0.
  • Fixed use of freed or relocated memory when apply_patch is #!cpp *this or refers to a value contained in #!cpp *this, in version 3.13.0.