Skip to content

Commit 2ad9332

Browse files
committed
Initial Commit
0 parents  commit 2ad9332

File tree

4 files changed

+176
-0
lines changed

4 files changed

+176
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
**/*.rs.bk

Cargo.lock

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "json_diff"
3+
version = "0.1.0"
4+
authors = ["Kshitij Tyagi <tkshitij@thoughtworks.com>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
serde_json = "1.0.41"

src/main.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
use serde_json;
2+
use serde_json::Map;
3+
use serde_json::Value;
4+
5+
fn main() {
6+
let data = r#"{
7+
"a":"b",
8+
"b":{
9+
"c":{
10+
"d":true,
11+
"e":5,
12+
"f":9,
13+
"h":{
14+
"i":true,
15+
"j":false
16+
}
17+
}
18+
}
19+
}"#;
20+
let data2 = r#"{
21+
"a":"b",
22+
"b":{
23+
"c":{
24+
"d":true,
25+
"e":6,
26+
"g":0,
27+
"h":{
28+
"i":false,
29+
"k":false
30+
}
31+
}
32+
}
33+
}"#;
34+
let value: Value = serde_json::from_str(data).unwrap();
35+
let value2: Value = serde_json::from_str(data2).unwrap();
36+
37+
if value == value2 {
38+
println!("JSONs match.");
39+
} else {
40+
match match_json(&value, &value2) {
41+
Mismatch::NoMismatch => println!("No mismatch was found."),
42+
Mismatch::ValueMismatch => println!("Mismatch at root."),
43+
Mismatch::ObjectMismatch(a,b,c) => {
44+
if let Some(left_keys) = a {
45+
println!("Following keys were not found in second object: {:?}", left_keys);
46+
}
47+
if let Some(right_keys) = b {
48+
println!("Following keys were not found in first object: {:?}", right_keys);
49+
}
50+
if let Some(unequal_keys) = c {
51+
println!("Following keys were not found to be equal: {:?}", unequal_keys);
52+
}
53+
}
54+
};
55+
}
56+
}
57+
58+
enum Mismatch {
59+
NoMismatch,
60+
ValueMismatch,
61+
ObjectMismatch(Option<Vec<String>>, Option<Vec<String>>, Option<Vec<String>>),
62+
}
63+
64+
fn match_json(value: &Value, value1: &Value) -> Mismatch {
65+
match (value, value1) {
66+
(Value::Object(a), Value::Object(b)) => {
67+
let (mut left, mut right, intersection) = intersect_maps(&a, &b);
68+
let mut unequal_keys = vec![];
69+
70+
for key in intersection {
71+
let append_key = |x: &String| {
72+
let mut n = String::from(&key);
73+
n.push('.');
74+
n.push_str(x);
75+
n.to_string()
76+
};
77+
let x = match_json(&a.get(&key).unwrap(), &b.get(&key).unwrap());
78+
if let Some(mut keys) = match x {
79+
Mismatch::NoMismatch => None,
80+
Mismatch::ValueMismatch => Some(vec![key]),
81+
Mismatch::ObjectMismatch(left_keys, right_keys, mismatch_keys) => {
82+
if let Some(left_keys) = left_keys {
83+
left.append(&mut left_keys.iter().map(append_key).collect::<Vec<String>>());
84+
}
85+
if let Some(right_keys) = right_keys {
86+
right.append(&mut right_keys.iter().map(append_key).collect::<Vec<String>>());
87+
}
88+
mismatch_keys
89+
},
90+
} {
91+
unequal_keys.append(&mut keys);
92+
}
93+
}
94+
Mismatch::ObjectMismatch(Some(left), Some(right), Some(unequal_keys))
95+
},
96+
(a, b) => {
97+
if a == b {
98+
Mismatch::NoMismatch
99+
} else {
100+
Mismatch::ValueMismatch
101+
}
102+
}
103+
}
104+
}
105+
106+
fn intersect_maps<'a>(a: &Map<String, Value>,
107+
b: &Map<String, Value>) -> (Vec<String>,
108+
Vec<String>, Vec<String>) {
109+
let mut intersection = vec![];
110+
let mut left = vec![];
111+
let mut right = vec![];
112+
for a_key in a.keys() {
113+
if b.contains_key(a_key) {
114+
intersection.push(String::from(a_key));
115+
} else {
116+
left.push(String::from(a_key));
117+
}
118+
}
119+
for b_key in b.keys() {
120+
if !a.contains_key(b_key) {
121+
right.push(String::from(b_key));
122+
}
123+
}
124+
(left, right, intersection)
125+
}

0 commit comments

Comments
 (0)