Definition
Have you ever filled out an online form where you only needed to update a couple of fields - say, your phone number and email - without re-entering your entire profile? You didn’t submit a blank form, and you didn’t need to re-type your name and address. You just provided the specific changes. JSON Merge Patch works the same way for APIs. Instead of sending a complete replacement of a resource, you send only the fields you want to change, and the server intelligently merges them with the existing data.
JSON Merge Patch (defined in RFC 7396) is elegantly simple: send a JSON object containing just the fields you want to update. New values replace old ones. Want to delete a field? Set it to null. Fields you don’t mention stay unchanged. If your user has {"name": "John", "email": "[email protected]", "phone": "555-1234"} and you send {"email": "[email protected]"}, only the email changes - name and phone remain untouched. Send {"phone": null} and the phone field gets deleted entirely.
The beauty of JSON Merge Patch is its simplicity - the patch document looks just like a regular JSON object, making it intuitive to write and read. However, this simplicity comes with limitations: you can’t explicitly set a field to null (that means “delete”), you can’t manipulate arrays element-by-element (the whole array gets replaced), and you can’t do conditional updates. For more complex operations, JSON Patch (RFC 6902) provides surgical precision. But for the majority of update scenarios - changing a name, updating an address, toggling a setting - JSON Merge Patch is the cleaner, simpler choice.
Example
Real-World Scenario 1: User Profile Update
A user changes their email address in your app. Your API doesn’t need their entire profile - just the email change. You send PATCH /users/123 with body {"email": "[email protected]"}. The server updates only the email, leaving name, avatar, preferences, and everything else untouched. The user didn’t need to re-submit their entire profile for one field change.
Real-World Scenario 2: E-Commerce Order Modification
A customer wants to change their shipping address before an order ships. Instead of resubmitting the entire order (items, quantities, payment info), you send a merge patch with just the address: {"shipping": {"street": "456 New Ave", "city": "Austin"}}. The order items, pricing, and everything else remain exactly as placed.
Real-World Scenario 3: Feature Toggles in Settings
An admin updates configuration settings for an application. They only need to change two out of dozens of settings: {"features": {"darkMode": true}, "notifications": {"email": false}}. The merge patch updates these specific nested values while preserving all other settings. Much cleaner than sending the entire configuration object.
Real-World Scenario 4: Removing Optional Fields
A user decides to remove their phone number from their profile for privacy. Sending {"phone": null} tells the server to delete the phone field entirely. This is JSON Merge Patch’s convention - null means “remove this field.” You couldn’t use merge patch if you legitimately needed to set something to null as a value (that’s a limitation).
Analogy
The Track Changes Document: JSON Merge Patch is like editing a document with track changes showing only what you modified. You don’t recreate the entire document - you mark the specific words or paragraphs that changed. The editor merges your changes into the original, preserving everything you didn’t touch.
The Medical Chart Update: When a doctor updates your medical chart, they don’t rewrite your entire history. They add or modify specific entries: “Updated: Blood pressure reading, allergies list.” Everything else in your chart remains unchanged. JSON Merge Patch is this focused update for data.
The Partial Form Submission: Imagine a form that only sends fields you actually changed. The unchanged fields aren’t submitted at all - they’re assumed to stay as-is. This is how JSON Merge Patch works: send what changed, preserve what didn’t.
The Renovation Blueprint: If you’re renovating a house and only updating the kitchen, you don’t submit blueprints for the entire house. You submit kitchen blueprints. The contractor knows everything else stays the same. JSON Merge Patch is the kitchen-only blueprint.
Code Example
// Original resource
const user = {
"name": "Alice",
"email": "[email protected]",
"phone": "+1234567890",
"age": 30,
"address": {
"city": "Seattle",
"country": "USA"
}
};
// JSON Merge Patch request
// PATCH /users/123
// Content-Type: application/merge-patch+json
const patch = {
"email": "[email protected]", // Update email
"phone": null, // Remove phone
"address": {
"city": "Portland" // Update nested city (replaces entire address!)
}
};
// Result after merge
const result = {
"name": "Alice", // Unchanged
"email": "[email protected]", // Updated
// phone removed
"age": 30, // Unchanged
"address": {
"city": "Portland" // Note: country is GONE! (see limitation)
}
};
// Implementation
function applyMergePatch(original, patch) {
if (patch === null) return null;
if (typeof patch !== 'object' || Array.isArray(patch)) return patch;
const result = { ...original };
for (const [key, value] of Object.entries(patch)) {
if (value === null) {
delete result[key];
} else if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
// Recursively merge objects
result[key] = applyMergePatch(result[key] || {}, value);
} else {
result[key] = value;
}
}
return result;
}
// API endpoint example (Express.js)
app.patch('/users/:id', (req, res) => {
const contentType = req.get('Content-Type');
if (contentType === 'application/merge-patch+json') {
const original = getUserById(req.params.id);
const patched = applyMergePatch(original, req.body);
saveUser(req.params.id, patched);
res.json(patched);
} else {
res.status(415).json({ error: 'Use application/merge-patch+json' });
}
});
// Limitations to be aware of:
// 1. Cannot set a value to null (null means "delete")
// 2. Arrays are replaced entirely, not merged
// 3. Cannot do conditional updates
// 4. Nested objects merge recursively (may have unexpected behavior)