From de6699dbb379d36d329ae95853274b1acc158d62 Mon Sep 17 00:00:00 2001 From: Ivan Dubrov Date: Fri, 9 Dec 2022 10:33:50 -0600 Subject: [PATCH] Fixing incorrect diffing for the whole document Closes #12 --- CHANGELOG.md | 9 +++++++++ src/diff.rs | 34 ++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6f77dd5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## 0.28.0 (2022-12-09) + +### Fixed + +- Fixed incorrect diffing for the whole document. Previously, differ would incorrectly yield path of `"/"` when the + whole document is replaced. The correct path should be `""`. This is a breaking change. + [#18](https://github.com/idubrov/json-patch/pull/18) diff --git a/src/diff.rs b/src/diff.rs index 9e76eeb..ecc900d 100644 --- a/src/diff.rs +++ b/src/diff.rs @@ -9,7 +9,7 @@ struct PatchDiffer { impl PatchDiffer { fn new() -> Self { Self { - path: "/".to_string(), + path: "".to_string(), patch: super::Patch(Vec::new()), shift: 0, } @@ -19,9 +19,7 @@ impl PatchDiffer { impl<'a> treediff::Delegate<'a, treediff::value::Key, Value> for PatchDiffer { fn push(&mut self, key: &treediff::value::Key) { use std::fmt::Write; - if self.path.len() != 1 { - self.path.push('/'); - } + self.path.push('/'); match *key { treediff::value::Key::Index(idx) => write!(self.path, "{}", idx - self.shift).unwrap(), treediff::value::Key::String(ref key) => append_path(&mut self.path, key), @@ -29,10 +27,7 @@ impl<'a> treediff::Delegate<'a, treediff::value::Key, Value> for PatchDiffer { } fn pop(&mut self) { - let mut pos = self.path.rfind('/').unwrap_or(0); - if pos == 0 { - pos = 1; - } + let pos = self.path.rfind('/').unwrap_or(0); self.path.truncate(pos); self.shift = 0; } @@ -151,10 +146,29 @@ mod tests { assert_eq!( p, serde_json::from_value(json!([ - { "op": "replace", "path": "/", "value": null }, + { "op": "replace", "path": "", "value": null }, + ])) + .unwrap() + ); + let mut left = json!({"title": "Hello!"}); + crate::patch(&mut left, &p).unwrap(); + } + + #[test] + pub fn diff_empty_key() { + let left = json!({"title": "Something", "": "Hello!"}); + let right = json!({"title": "Something", "": "Bye!"}); + let p = super::diff(&left, &right); + assert_eq!( + p, + serde_json::from_value(json!([ + { "op": "replace", "path": "/", "value": "Bye!" }, ])) .unwrap() ); + let mut left_patched = json!({"title": "Something", "": "Hello!"}); + crate::patch(&mut left_patched, &p).unwrap(); + assert_eq!(left_patched, right); } #[test] @@ -164,7 +178,7 @@ mod tests { assert_eq!( p, serde_json::from_value(json!([ - { "op": "replace", "path": "/", "value": { "title": "Hello!" } }, + { "op": "replace", "path": "", "value": { "title": "Hello!" } }, ])) .unwrap() );