use super::{OutputFormatter, OutputOptions};
use crate::types::GrepResult;
use anyhow::Result;
use serde_json::json;
pub struct JsonFormatter {
options: OutputOptions,
}
impl JsonFormatter {
pub fn new(options: OutputOptions) -> Self {
Self { options }
}
}
impl Default for JsonFormatter {
fn default() -> Self {
Self::new(OutputOptions::default())
}
}
impl OutputFormatter for JsonFormatter {
fn format_result(&self, result: &GrepResult) -> Result<String> {
if self.options.count_mode {
let output = json!({
"notebook": result.notebook,
"count": result.matches.len(),
});
Ok(serde_json::to_string_pretty(&output)?)
} else {
let output = json!({
"notebook": result.notebook,
"matches": result.matches,
"total": result.matches.len(),
});
Ok(serde_json::to_string_pretty(&output)?)
}
}
fn format_results(&self, results: &[GrepResult]) -> Result<String> {
let total_matches: usize = results.iter().map(|r| r.matches.len()).sum();
if self.options.count_mode {
let counts: Vec<_> = results
.iter()
.map(|r| {
json!({
"notebook": r.notebook,
"count": r.matches.len(),
})
})
.collect();
let output = json!({
"counts": counts,
"total_notebooks": results.len(),
"total_matches": total_matches,
});
Ok(serde_json::to_string_pretty(&output)?)
} else {
let output = json!({
"results": results,
"total_notebooks": results.len(),
"total_matches": total_matches,
});
Ok(serde_json::to_string_pretty(&output)?)
}
}
}