jatch/patch/
mod.rs

1pub mod apply;
2pub mod walk;
3
4use crate::Path;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8/// A Json Patch operation
9#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
10#[serde(tag = "op")]
11pub enum Patch {
12    /// Inserts `value` into the location in the document referred to by `path`
13    #[serde(rename = "add")]
14    Add {
15        /// The path to add to
16        /// If the path does not exist, but its parent does, the path will be created
17        /// If the parent of this path doesn't exist, the operation will fail
18        path: Path,
19        /// The value to add
20        value: Value,
21    },
22    /// Remove the value at a location in the document referred to by `path`
23    #[serde(rename = "remove")]
24    Remove {
25        /// The path to remove from
26        /// If the path doesn't exist, the operation will fail
27        path: Path,
28    },
29    /// Replace the contents of `path` with `value`
30    /// This is equivalent to a `Replace` then an `Add`
31    #[serde(rename = "replace")]
32    Replace {
33        /// The path to replace
34        path: Path,
35        /// The value to replace
36        value: Value,
37    },
38    /// Copy the value at `from` to the location referred to by `path`
39    #[serde(rename = "copy")]
40    Copy {
41        /// The path to copy from
42        from: Path,
43        /// The path to copy to
44        path: Path,
45    },
46    /// Move the value at `from` to the location referred to by `path`
47    /// Equivalent to a `Copy` followed by a `Remove`
48    #[serde(rename = "move")]
49    Move {
50        /// The path to move from
51        from: Path,
52        /// the path to move to
53        path: Path,
54    },
55    /// Check that the location referred to by `path` matches `value`
56    /// If the the document does not contain `value` at `path`, an [Error::FailedTest] is returned
57    #[serde(rename = "test")]
58    Test {
59        /// The path to test
60        path: Path,
61        /// The value expected at `path`
62        value: Value,
63    },
64}
65
66#[cfg(test)]
67mod test {
68    use serde_json::json;
69
70    use super::*;
71
72    #[test]
73    fn should_deserialize_patches() {
74        use serde_json::from_str;
75
76        assert_eq!(
77            from_str::<Patch>(r#"{"op": "add", "path": "/foo", "value": "hello"}"#).unwrap(),
78            Patch::Add {
79                path: Path::new("/foo"),
80                value: json!("hello"),
81            }
82        );
83
84        assert_eq!(
85            from_str::<Patch>(r#"{"op": "remove", "path": "/foo"}"#).unwrap(),
86            Patch::Remove {
87                path: Path::new("/foo"),
88            }
89        );
90
91        assert_eq!(
92            from_str::<Patch>(r#"{"op": "replace", "path": "/foo", "value": 123}"#).unwrap(),
93            Patch::Replace {
94                path: Path::new("/foo"),
95                value: json!(123),
96            }
97        );
98
99        assert_eq!(
100            from_str::<Patch>(r#"{"op": "copy", "from": "/foo", "path": "/to"}"#).unwrap(),
101            Patch::Copy {
102                from: Path::new("/foo"),
103                path: Path::new("/to"),
104            }
105        );
106
107        assert_eq!(
108            from_str::<Patch>(r#"{"op": "move", "from": "/foo", "path": "/to"}"#).unwrap(),
109            Patch::Move {
110                from: Path::new("/foo"),
111                path: Path::new("/to"),
112            }
113        );
114
115        assert_eq!(
116            from_str::<Patch>(r#"{"op": "test", "path": "/foo", "value": true}"#).unwrap(),
117            Patch::Test {
118                path: Path::new("/foo"),
119                value: json!(true),
120            }
121        );
122    }
123}