use super::Formatter;
use crate::{Change, Diff, FormatError};
use serde_json::json;
#[derive(Debug)]
pub struct JsonFormatter {
pretty: bool,
}
impl JsonFormatter {
pub fn new() -> Self {
Self { pretty: false }
}
pub fn pretty(mut self) -> Self {
self.pretty = true;
self
}
}
impl Default for JsonFormatter {
fn default() -> Self {
Self::new()
}
}
impl Formatter for JsonFormatter {
fn format(&self, diff: &Diff) -> Result<String, FormatError> {
let mut output = serde_json::Map::new();
for (path, change) in diff.changes() {
let change_obj = match change {
Change::Added(val) => json!({
"type": "added",
"value": val,
}),
Change::Removed(val) => json!({
"type": "removed",
"value": val,
}),
Change::Modified { from, to } => json!({
"type": "modified",
"from": from,
"to": to,
}),
Change::Elided { reason, count } => json!({
"type": "elided",
"reason": reason,
"count": count,
}),
};
output.insert(path.to_string(), change_obj);
}
if self.pretty {
serde_json::to_string_pretty(&output).map_err(FormatError::Json)
} else {
serde_json::to_string(&output).map_err(FormatError::Json)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Path;
use serde_value::Value;
#[test]
fn test_json_format() {
let mut diff = Diff::new();
diff.insert(Path::root().field("x"), Change::Added(Value::I64(42)));
let formatter = JsonFormatter::new();
let output = formatter.format(&diff).unwrap();
assert!(output.contains("\"type\":\"added\""));
}
}