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}