idnits 2.17.1 draft-snell-merge-patch-08.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- No issues found here. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year == The document seems to lack the recommended RFC 2119 boilerplate, even if it appears to use RFC 2119 keywords. (The document does seem to have the reference to RFC 2119 which the ID-Checklist requires). -- The document date (January 7, 2013) is 4127 days in the past. Is this intentional? Checking references for intended status: Informational ---------------------------------------------------------------------------- -- Looks like a reference, but probably isn't: '1' on line 351 -- Looks like a reference, but probably isn't: '2' on line 351 -- Looks like a reference, but probably isn't: '3' on line 341 ** Obsolete normative reference: RFC 4627 (Obsoleted by RFC 7158, RFC 7159) Summary: 1 error (**), 0 flaws (~~), 2 warnings (==), 4 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 Network Working Group J. Snell 3 Internet-Draft January 7, 2013 4 Intended status: Informational 5 Expires: July 11, 2013 7 The application/json-merge-patch Media Type 8 draft-snell-merge-patch-08 10 Abstract 12 This specification defines the application/json-merge-patch media 13 type and it's intended use with the HTTP PATCH method defined by RFC 14 5789. 16 Status of this Memo 18 This Internet-Draft is submitted to IETF in full conformance with the 19 provisions of BCP 78 and BCP 79. 21 Internet-Drafts are working documents of the Internet Engineering 22 Task Force (IETF). Note that other groups may also distribute 23 working documents as Internet-Drafts. The list of current Internet- 24 Drafts is at http://datatracker.ietf.org/drafts/current/. 26 Internet-Drafts are draft documents valid for a maximum of six months 27 and may be updated, replaced, or obsoleted by other documents at any 28 time. It is inappropriate to use Internet-Drafts as reference 29 material or to cite them other than as "work in progress." 31 This Internet-Draft will expire on July 11, 2013. 33 Copyright Notice 35 Copyright (c) 2013 IETF Trust and the persons identified as the 36 document authors. All rights reserved. 38 This document is subject to BCP 78 and the IETF Trust's Legal 39 Provisions Relating to IETF Documents 40 (http://trustee.ietf.org/license-info) in effect on the date of 41 publication of this document. Please review these documents 42 carefully, as they describe your rights and restrictions with respect 43 to this document. Code Components extracted from this document must 44 include Simplified BSD License text as described in Section 4.e of 45 the Trust Legal Provisions and are provided without warranty as 46 described in the Simplified BSD License. 48 Table of Contents 50 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 51 2. The "application/json-merge-patch" Media Type . . . . . . . . . 3 52 3. IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 6 53 4. Security Considerations . . . . . . . . . . . . . . . . . . . . 7 54 5. Normative References . . . . . . . . . . . . . . . . . . . . . 7 55 Appendix A. Example JavaScript Implementation . . . . . . . . . . 7 56 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 9 58 1. Introduction 60 This specification defines the JSON "Merge Patch" document format, 61 processing rules, and associated MIME media type identifier. The 62 Merge Patch format is primarily intended for use with the HTTP PATCH 63 method [RFC5789] as a means of describing a set of modifications to a 64 subset of target resource's content. 66 For example, given the following original JSON document: 68 { 69 "a": "b", 70 "c": { 71 "d": "e" 72 } 73 } 75 A change to the value of the "a" member can be described simply as: 77 PATCH /target HTTP/1.1 78 Host: example.org 79 Content-Type: application/json-merge-patch 81 {"a": "z"} 83 When applied to the target resource, only the value of the "a" member 84 will be modified, leaving the remaining content untouched. 86 The Merge Patch format generally supports two types of changes: 87 removing and setting JSON object members. JSON arrays are treated 88 the same as JSON primitives: the whole value can be replaced, but not 89 partially modified. The JSON null value is given a special meaning 90 to indicate the removal of an existing value. These constraints 91 allow Merge Patch to use a format that closely mimics the document 92 being modified. The constraints mean Merge Patch is suitable for 93 patching JSON documents that primarily use objects for their 94 structure, and do not make use of explicit null values. The Merge 95 Patch format is not appropriate for all JSON syntaxes. 97 In this document, the key words "MUST", "MUST NOT", "REQUIRED", 98 "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", 99 and "OPTIONAL" are to be interpreted as described in [RFC2119]. 101 2. The "application/json-merge-patch" Media Type 103 The "application/json-merge-patch" Media Type is used to identify 104 JSON documents that describe, by example, a set of changes that are 105 to be made to a target resource. When used within an HTTP PATCH 106 request, it is the responsibility of the server receiving and 107 processing the request to inspect the payload entity and determine 108 the specific set of operations that are to be performed to modify the 109 target resource. 111 For example, given the following example JSON document: 113 { 114 "title": "Goodbye!", 115 "author" : { 116 "givenName" : "John", 117 "familyName" : "Doe" 118 }, 119 "tags":["example","sample"], 120 "content": "This will be unchanged" 121 } 123 If the intent is to change the value of the "title" member to from 124 "Goodbye!" to the value "Hello!", add a new "phoneNumber" member, 125 remove the "familyName" member from the "author" object, and remove 126 the word sample from the "tags" Array, the user-agent would send the 127 following request: 129 PATCH /my/resource HTTP/1.1 130 Host: example.org 131 Content-Type: application/json-merge-patch; charset="UTF-8" 133 { 134 "title": "Hello!", 135 "phoneNumber": "+01-123-456-7890", 136 "author": { 137 "familyName": null 138 }, 139 "tags": ["example"] 140 } 142 Upon receiving the request, the server is responsible for inspecting 143 the payload and determining, based on it's own understanding of the 144 target resource media type and the underlying data model of the 145 target resource, what specific operations will be applied to modify 146 the resource. 148 A server receiving this patch request MUST apply the following rules 149 to determine the specific set of change operations to be performed: 150 1. If either the root of the JSON data provided in the payload or 151 the root of the target resource are JSON Arrays, the target 152 resource is to be replaced, in whole, by the provided data. Any 153 object member contained in the provided data whose value is 154 explicitly null is to be treated as if the member was undefined. 155 2. If the root of the JSON data provided in the payload is an 156 Object, for each distinct member specified within that object: 157 * If the member is currently undefined within the target 158 resource, and the given value is not null, the member and the 159 value are to be added to the target. Any object member 160 contained in the provided data whose value is explicitly null 161 is to be treated as if the member were undefined. 162 * If the value is explicitly set to null and that member is 163 currently defined within the target resource, the existing 164 member is removed. 165 * If the value is either a non-null JSON primitive or an Array 166 and that member is currently defined within the target 167 resource, the existing value for that member is to be replaced 168 with that provided. Any object member contained in the 169 provided data whose value is explicitly null is to be treated 170 as if the member were undefined. 171 * If the value is a JSON object and that member is currently 172 defined for the target resource and the existing value is a 173 JSON primitive or Array, the existing value is to be replaced 174 in whole by the object provided. Any object member contained 175 in the provided data whose value is explicitly null is to be 176 treated as if the member was undefined. 177 * If the value is a JSON object and that member is currently 178 defined within the target resource and the existing value is 179 also a JSON object, then recursively apply Rule #2 to each 180 object. 181 * Any member currently defined within the target resource that 182 does not explicitly appear within the patch is to remain 183 untouched and unmodified. 185 Applying these rules to the previous example, the set of specific 186 change operations derived from the request are: 187 o Change the existing value of the "title" member from "Goodbye!" to 188 "Hello!", 189 o Add the "phoneNumber" member with a value of "+01-123-456-7890", 190 o Remove the "familyName" member from the current object value 191 associated with the "author" member, and 192 o Change the existing value of the "tags" member from 193 ["example","sample"] to ["example"]. 195 The resulting JSON document would be similar to the following (the 196 specific ordering of members within JSON documents is insigificant): 198 { 199 "title": "Hello!", 200 "author" : { 201 "givenName" : "John" 202 }, 203 "tags":["example"], 204 "content": "This will be unchanged", 205 "phoneNumber": "+01-123-456-7890" 206 } 208 Once the set of intended modifications is derived from the request, 209 the server is free to determine the appropriateness of the 210 modification based on it's own understanding of the target resource. 211 For instance, in the previous example, it is possible that the 212 "familyName" member might be required within the target resource and 213 cannot be removed. Note that in such cases, per [RFC5789], Section 214 2, the server is REQUIRED to reject the entire PATCH request using an 215 HTTP error response code appropriate to the error condition. 217 If the request attempts to remove a member from the target resource 218 that does not currently exist, the server SHOULD NOT consider the 219 request to be in error. The requested removal operation is simply to 220 be ignored by the server as the final modified state of the target 221 resource will still accurately reflect the user-agent's original 222 intent. 224 3. IANA Considerations 226 This specification registers the following additional MIME Media 227 Types: 229 Type name: application 230 Subtype name: json-merge-patch 231 Required parameters: None 232 Optional parameters: "charset" : Specifies the character set 233 encoding. If not specified, a default of "UTF-8" is assumed. 234 Encoding considerations: Resources that use the "application/ 235 json-merge-patch" media type are required to conform to the 236 "application/json" Media Type and are therefore subject to the 237 same encoding considerations specified in Section 6 [RFC4627]. 238 Security considerations: As defined in this specification 239 Published specification: This specification. 241 Applications that use this media type: None currently known. 242 Additional information: 243 Magic number(s): N/A 244 File extension(s): N/A 245 Macintosh file type code(s): TEXT 246 Person & email address to contact for further information: James M 247 Snell 248 Intended usage: COMMON 249 Restrictions on usage: None. 250 Author: James M Snell 251 Change controller: IESG 253 4. Security Considerations 255 The "application/json-merge-patch" Media Type allows user agents to 256 indicate their intention that the server determine the specific set 257 of change operations to be applied to a target resource. As such, it 258 is the server's responsibility to determine the appropriateness of 259 any given change as well as the user agent's authorization to request 260 such changes. How such determinations are made is considered out of 261 the scope of this specification. 263 All of the the security considerations discussed in Section 5 264 [RFC5789] apply to all uses of the HTTP PATCH method with the 265 "application/json-merge-patch" Media Type. 267 5. Normative References 269 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 270 Requirement Levels", BCP 14, RFC 2119, March 1997. 272 [RFC4627] Crockford, D., "The application/json Media Type for 273 JavaScript Object Notation (JSON)", RFC 4627, July 2006. 275 [RFC5789] Dusseault, L. and J. Snell, "PATCH Method for HTTP", 276 RFC 5789, March 2010. 278 Appendix A. Example JavaScript Implementation 280 The following example implementation is provided as is, without 281 warranty. It is provided in the public domain. 283 // Apply the patch to the original, return the 284 // modified object... this will mutate the 285 // passed in object in place as well... 287 function apply(orig, patch) { 288 if (patch == null) 289 return orig; 290 else if (patch instanceof Array) 291 orig = purge_nulls(patch); 292 else if (is_primitive(patch)) 293 orig = patch; 294 else if (patch instanceof Object) { 295 for (m in patch) { 296 if (orig.hasOwnProperty(m)) { 297 if (patch[m] == null) 298 delete orig[m]; 299 else { 300 if (is_primitive(patch[m])) 301 orig[m] = patch[m]; 302 else { 303 if (orig[m] instanceof Array) 304 orig[m] = purge_nulls(patch[m]); 305 else 306 orig[m] = apply(orig[m],patch[m]); 307 } 308 } 309 } else if (patch[m] != null) 310 orig[m] = purge_nulls(patch[m]); 311 } 312 } 313 return orig; 314 } 316 function is_primitive(val) { 317 var m = typeof val; 318 return m == 'string' || 319 m == 'number' || 320 m == 'boolean'; 321 } 323 function purge_nulls(obj) { 324 for (m in obj) { 325 if (obj[m] == null) { 326 if (obj instanceof Array) 327 obj.splice(m,1); 328 else 329 delete(obj[m]); 330 } else if (obj[m] instanceof Object) 331 purge_nulls(obj[m]); 332 } 333 return obj; 335 } 337 // Define the original object... 338 var orig = { 339 "a": "b", 340 "c": { 341 "d": [1,2,3], 342 "e": { 343 "f": 1 344 } 345 } 346 } 348 // Define the patch... 349 var patch = { 350 "c": { 351 "d": [1,2], 352 "e": { 353 "f": null 354 } 355 } 356 } 358 // Apply the patch... 359 var modified = apply(orig,patch); 361 Author's Address 363 James M Snell 365 Email: jasnell@gmail.com