Skip to main content

serde_patch/
apply_patch_mut.rs

1use serde::{Serialize, de::DeserializeOwned};
2use serde_json::{Map, Value};
3
4/// Applies a JSON Merge Patch (RFC 7396) in-place.
5///
6/// Modifies the current value directly.
7///
8/// # Example
9///
10/// ```rust
11/// #[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
12/// struct User { id: u32, name: String }
13///
14/// let mut user = User { id: 1, name: "old".to_string() };
15/// let patch = r#"{ "name": "new" }"#;
16///
17/// serde_patch::apply_mut(&mut user, patch).unwrap();
18/// assert_eq!(user.name, "new");
19/// assert_eq!(user.id, 1);
20/// ```
21pub fn apply_mut<T, P>(current: &mut T, patch: P) -> Result<(), serde_json::Error>
22where
23    T: Serialize + DeserializeOwned,
24    P: AsRef<[u8]>,
25{
26    let mut current_val = serde_json::to_value(&current)?;
27    let patch_val: Value = serde_json::from_slice(patch.as_ref())?;
28    merge_patch(&mut current_val, &patch_val);
29    *current = serde_json::from_value(current_val)?;
30    Ok(())
31}
32
33/// Recursively merges a patch into a target JSON value (internal).
34fn merge_patch(target: &mut Value, patch: &Value) {
35    if let Value::Object(patch_map) = patch {
36        if !target.is_object() {
37            *target = Value::Object(Map::new());
38        }
39        let target_map = target.as_object_mut().unwrap();
40        for (key, patch_value) in patch_map {
41            if patch_value.is_null() {
42                target_map.remove(key);
43            } else {
44                let target_entry = target_map.entry(key.clone()).or_insert(Value::Null);
45                merge_patch(target_entry, patch_value);
46            }
47        }
48    } else {
49        *target = patch.clone();
50    }
51}