Implementing Partial Updates
1. Using PATCH Method
| Aspect | PATCH | PUT |
| Scope | Partial change | Full replacement |
| Body | Changed fields only | Entire resource |
| Idempotent | Depends on patch type | Yes |
| Content-Type | merge-patch+json or json-patch+json | application/json |
2. Implementing JSON Patch
RFC 6902 — sequence of operations on JSON document.
| op | Description |
add | Add value to path |
remove | Remove value at path |
replace | Replace value at path |
move | Move from one path to another |
copy | Copy from one path to another |
test | Conditional check (atomic precondition) |
Example: JSON Patch
PATCH /users/42
Content-Type: application/json-patch+json
[
{ "op": "replace", "path": "/email", "value": "new@x.com" },
{ "op": "add", "path": "/tags/-", "value": "premium" },
{ "op": "remove", "path": "/middleName" }
]
3. Using JSON Merge Patch
RFC 7396 — simpler: send fields to change; null = delete.
Example: JSON Merge Patch
PATCH /users/42
Content-Type: application/merge-patch+json
{
"email": "new@x.com",
"middleName": null, // remove field
"preferences": {
"newsletter": false // merged into existing preferences
}
}
| Limitation | Workaround |
| Cannot set field to literal null | Use JSON Patch |
| Cannot patch array elements individually | Use JSON Patch with index |
4. Validating Patch Operations
| Check | Failure Code |
| Path exists (replace/remove) | 422 |
| Path is patchable (allowlist) | 403 |
| Value matches schema | 422 |
test op succeeds | 409 (precondition failed) |
5. Handling Nested Field Updates
| Patch Format | Nested Update |
| JSON Patch | {"op":"replace","path":"/address/city","value":"NYC"} |
| JSON Merge Patch | Deep merge of nested objects |
6. Implementing Atomic Patch Operations
Warning: JSON Patch is atomic — all operations succeed or none apply. Wrap in DB transaction.
| Tool | Notes |
| DB transaction | BEGIN ... COMMIT/ROLLBACK |
test op | Precondition for atomic conditional update |
7. Returning Updated Resource
| Status | Body |
| 200 OK | Full updated resource |
| 204 No Content | No body (client must refetch if needed) |
| 200 + Prefer header | Prefer: return=minimal ↔ return=representation |
8. Handling Patch Conflicts
| Strategy | Implementation |
| If-Match + ETag | 412 Precondition Failed on conflict |
JSON Patch test | 409 if test fails |
| Version field | Compare in WHERE clause |
9. Documenting Patchable Fields
| Documentation | Content |
| Allowed fields | List patchable paths |
| Read-only fields | id, createdAt — return 403 on patch |
| Side effects | Cascading updates, denormalization |
10. Using PUT for Full Replacement vs PATCH
| Use PUT When | Use PATCH When |
| Client has full resource | Client has partial changes |
| Simple write semantics | Bandwidth-sensitive |
| Resource creation at known URI | Field-by-field updates |
| Form submissions | Mobile clients, slow networks |