1use console::Style;
2use dissimilar::{Chunk, diff};
3use serde_json::Value;
4use std::fmt::Write;
5
6pub fn get_json_diff(expected: &Value, actual: &Value) -> String {
8 let expected_str =
9 serde_json::to_string_pretty(expected).unwrap_or_else(|_| expected.to_string());
10 let actual_str = serde_json::to_string_pretty(actual).unwrap_or_else(|_| actual.to_string());
11
12 let diff_chunks = diff(&expected_str, &actual_str);
13
14 let mut output = String::new();
15 let _ = writeln!(output, "Diff (Expected - / Actual +):");
16
17 for chunk in diff_chunks {
18 match chunk {
19 Chunk::Equal(text) => {
20 let style = Style::new().dim();
21 let _ = write!(output, "{}", style.apply_to(text));
22 }
23 Chunk::Delete(text) => {
24 let style = Style::new().red();
25 let _ = write!(output, "{}", style.apply_to(text));
26 }
27 Chunk::Insert(text) => {
28 let style = Style::new().green();
29 let _ = write!(output, "{}", style.apply_to(text));
30 }
31 }
32 }
33
34 output
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use serde_json::json;
41
42 #[test]
43 fn test_get_json_diff() {
44 let expected = json!({
45 "name": "Alice",
46 "age": 30
47 });
48 let actual = json!({
49 "name": "Bob",
50 "age": 30
51 });
52
53 let diff = get_json_diff(&expected, &actual);
54 println!("{}", diff);
55
56 assert!(diff.contains("Alice"));
58 assert!(diff.contains("Bob"));
59 assert!(diff.contains("\"age\": 30"));
60 }
61}