RFC 7396

JSON Merge Patch

πŸ“… published October 2014, from ietf

RFC 7396: JSON Merge Patch πŸŽ€

Okay bestie, this is RFC 7396, called JSON Merge Patch πŸ’…. It was written by Paul Hoffman of the VPN Consortium and James M. Snell 🫢. It's a Standards Track document, dated October 2014, with ISSN 2070-1721 ✨. It obsoletes RFC 7386, so that's the older version this one replaces πŸ™ˆ.

Abstract ✨

Here's the vibe: this spec defines the JSON merge patch format and how to process it πŸ¦‹. It's mainly meant to go with the HTTP PATCH method, as a way to describe a bunch of changes to a target resource's content πŸ’œ.

Status of This Memo πŸ“œ

This is an Internet Standards Track document πŸ”₯.

It's a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG) πŸ‘‘. If you want more on Internet Standards, check Section 2 of RFC 5741 🌸.

For the latest status, errata, and how to send feedback, go to http://www.rfc-editor.org/info/rfc7396 🧚.

Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved πŸ’–.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info), as in effect on the date of publication. Please read these carefully, because they spell out your rights and restrictions for this document πŸ™ˆ. Code Components pulled out of this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Simplified BSD License ⚠️.

Table of Contents πŸ—ΊοΈ

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   2
2.  Processing Merge Patch Documents  . . . . . . . . . . . . . .   3
3.  Example . . . . . . . . . . . . . . . . . . . . . . . . . . .   4
4.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .   5
5.  Security Considerations . . . . . . . . . . . . . . . . . . .   6
6.  References  . . . . . . . . . . . . . . . . . . . . . . . . .   7
  6.1.  Normative References  . . . . . . . . . . . . . . . . . .   7
  6.2.  Informative References  . . . . . . . . . . . . . . . . .   7
Appendix A.  Example Test Cases . . . . . . . . . . . . . . . . .   8
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . .   9
Authors' Addresses  . . . . . . . . . . . . . . . . . . . . . . .   9

1. Introduction πŸŽ€

This spec defines the JSON merge patch document format, its processing rules, and an associated MIME media type identifier πŸ’…. It's mainly meant to be used with the HTTP PATCH method [RFC5789] as a way to describe a set of changes to a target resource's content ✨.

So a JSON merge patch document describes the changes you want made to a target JSON document, and it's written in a syntax that looks a lot like the document it's modifying πŸ¦‹. The recipient figures out the exact changes by comparing the patch to the target's current content πŸ”₯. If the patch has members that aren't in the target, they get added. If the target already has the member, its value gets replaced. And null values get a special job: they mean "remove this existing value from the target" πŸ’€.

Here's an example. Say you start with this JSON document:

{
  "a": "b",
  "c": {
    "d": "e",
    "f": "g"
  }
}

To change the value of "a" and remove "f", you can send:

PATCH /target HTTP/1.1
Host: example.org
Content-Type: application/merge-patch+json

{
  "a":"z",
  "c": {
    "f": null
  }
}

Once that's applied to the target resource, "a" gets replaced with "z" and "f" is removed, and everything else stays untouched 🌸.

This design is a big deal, because it means merge patch documents are a great fit for changing JSON documents that mostly use objects for their structure and don't use explicit null values πŸ“. The merge patch format isn't right for every JSON syntax, though πŸ™ˆ.

2. Processing Merge Patch Documents 🧚

JSON merge patch documents describe, by example, the changes to be made to a target resource πŸ¦‹. The recipient is responsible for comparing the merge patch against the target resource's current content to work out the exact set of change operations to apply πŸ’œ.

To apply a merge patch document to a target resource, the system produces the effect of the following function, written in pseudocode. The function is called MergePatch and takes two arguments: the target resource document and the merge patch document. The Target argument can be any JSON value or undefined. The Patch argument can be any JSON value ✨.

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

A few things to note about this function πŸ‘€. If the patch is anything other than an object, the result is always to replace the entire target with the entire patch πŸ’…. And you can't patch just part of a target that isn't an object, like swapping out only some values in an array πŸ™…β€β™€οΈ.

MergePatch works on data items, not on textual representation 🌈. There's no expectation that it keeps things like white space, member ordering, number precision beyond what the target's implementation can hold, and so on ✨. Also, even if the target implementation allows multiple name/value pairs with the same name, the result of MergePatch on those objects isn't defined 😭.

3. Example 🌷

Here's an example JSON document:

{
  "title": "Goodbye!",
  "author" : {
    "givenName" : "John",
    "familyName" : "Doe"
  },
  "tags":[ "example", "sample" ],
  "content": "This will be unchanged"
}

Say a user agent wants to change "title" from "Goodbye!" to "Hello!", add a new "phoneNumber" member, remove "familyName" from the "author" object, and replace the "tags" array so it doesn't include the word "sample". It would send this request πŸ’–:

PATCH /my/resource HTTP/1.1
Host: example.org
Content-Type: application/merge-patch+json

{
  "title": "Hello!",
  "phoneNumber": "+01-123-456-7890",
  "author": {
    "familyName": null
  },
  "tags": [ "example" ]
}

And the resulting JSON document would be:

{
  "title": "Hello!",
  "author" : {
    "givenName" : "John"
  },
  "tags": [ "example" ],
  "content": "This will be unchanged",
  "phoneNumber": "+01-123-456-7890"
}

4. IANA Considerations πŸ“š

This spec registers an additional MIME media type πŸŽ€. Here's the registration:

   Type name: application

   Subtype name: merge-patch+json

   Required parameters: None

   Optional parameters: None

   Encoding considerations: Resources that use the "application/
   merge-patch+json" media type are required to conform to the
   "application/json" media type and are therefore subject to the
   same encoding considerations specified in Section 8 of [RFC7159].

   Security considerations: As defined in this specification

   Published specification: This specification.

   Applications that use this media type: None currently known.

   Additional information:

      Magic number(s): N/A

      File extension(s): N/A

      Macintosh file type code(s): TEXT

   Person & email address to contact for further information: IESG

   Intended usage: COMMON

   Restrictions on usage: None

   Author: James M. Snell <jasnell@gmail.com>

   Change controller: IESG

5. Security Considerations πŸ”

Okay, this section is serious 😭. The "application/merge-patch+json" media type lets user agents signal that they want the server to work out the exact set of change operations to apply to a target resource ⚠️. That means it's on the server to decide whether any given change is appropriate, and whether the user agent is authorized to ask for it πŸ›‘οΈ. How those decisions get made is out of scope for this spec πŸ™ˆ.

All of the security considerations discussed in Section 5 of [RFC5789] apply to every use of the HTTP PATCH method with the "application/merge-patch+json" media type πŸ’€.

6. References πŸ“–

6.1. Normative References

[RFC7159]  Bray, T., "The JavaScript Object Notation (JSON) Data
           Interchange Format", RFC 7159, March 2014,
           <http://www.rfc-editor.org/info/rfc7159>.

6.2. Informative References

[RFC5789]  Dusseault, L. and J. Snell, "PATCH Method for HTTP", RFC
           5789, March 2010,
           <http://www.rfc-editor.org/info/rfc5789>.

Appendix A. Example Test Cases πŸ§ͺ

Here are the test cases, so you can see exactly how it's supposed to go πŸ’…:

ORIGINAL        PATCH            RESULT
------------------------------------------
{"a":"b"}       {"a":"c"}       {"a":"c"}

{"a":"b"}       {"b":"c"}       {"a":"b",
                                 "b":"c"}

{"a":"b"}       {"a":null}      {}

{"a":"b",       {"a":null}      {"b":"c"}
 "b":"c"}

{"a":["b"]}     {"a":"c"}       {"a":"c"}

{"a":"c"}       {"a":["b"]}     {"a":["b"]}

{"a": {         {"a": {         {"a": {
  "b": "c"}       "b": "d",       "b": "d"
}                 "c": null}      }
                }               }

{"a": [         {"a": [1]}      {"a": [1]}
  {"b":"c"}
 ]
}

["a","b"]       ["c","d"]       ["c","d"]

{"a":"b"}       ["c"]           ["c"]

{"a":"foo"}     null            null

{"a":"foo"}     "bar"           "bar"

{"e":null}      {"a":1}         {"e":null,
                                 "a":1}

[1,2]           {"a":"b",       {"a":"b"}
                 "c":null}

{}              {"a":            {"a":
                 {"bb":           {"bb":
                  {"ccc":          {}}}
                   null}}}

Acknowledgments 🫢

Lots of people contributed big ideas to this document 🌟. They include, but aren't limited to, James Manger, Matt Miller, Carsten Bormann, Bjoern Hoehrmann, Pete Resnick, and Richard Barnes πŸ’œ.

Authors' Addresses πŸ’Œ

Paul Hoffman, VPN Consortium EMail: paul.hoffman@vpnc.org

James M. Snell EMail: jasnell@gmail.com

πŸ“¦ where this page comes from