syncable_cli/analyzer/hadolint/formatter/
json.rs1use crate::analyzer::hadolint::formatter::Formatter;
7use crate::analyzer::hadolint::lint::LintResult;
8use crate::analyzer::hadolint::types::Severity;
9use serde::Serialize;
10use std::io::Write;
11
12#[derive(Debug, Clone, Default)]
14pub struct JsonFormatter {
15 pub pretty: bool,
17}
18
19impl JsonFormatter {
20 pub fn new() -> Self {
22 Self::default()
23 }
24
25 pub fn pretty() -> Self {
27 Self { pretty: true }
28 }
29}
30
31#[derive(Debug, Serialize)]
33struct JsonFailure {
34 line: u32,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 column: Option<u32>,
37 code: String,
38 message: String,
39 level: String,
40 file: String,
41}
42
43impl Formatter for JsonFormatter {
44 fn format<W: Write>(
45 &self,
46 result: &LintResult,
47 filename: &str,
48 writer: &mut W,
49 ) -> std::io::Result<()> {
50 let failures: Vec<JsonFailure> = result
51 .failures
52 .iter()
53 .map(|f| JsonFailure {
54 line: f.line,
55 column: f.column,
56 code: f.code.to_string(),
57 message: f.message.clone(),
58 level: match f.severity {
59 Severity::Error => "error",
60 Severity::Warning => "warning",
61 Severity::Info => "info",
62 Severity::Style => "style",
63 Severity::Ignore => "ignore",
64 }
65 .to_string(),
66 file: filename.to_string(),
67 })
68 .collect();
69
70 let json = if self.pretty {
71 serde_json::to_string_pretty(&failures)
72 } else {
73 serde_json::to_string(&failures)
74 }
75 .map_err(std::io::Error::other)?;
76
77 writeln!(writer, "{}", json)
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::analyzer::hadolint::types::CheckFailure;
85
86 #[test]
87 fn test_json_output() {
88 let mut result = LintResult::new();
89 result.failures.push(CheckFailure::new(
90 "DL3008",
91 Severity::Warning,
92 "Pin versions in apt get install",
93 5,
94 ));
95
96 let formatter = JsonFormatter::new();
97 let output = formatter.format_to_string(&result, "Dockerfile");
98
99 assert!(output.contains("DL3008"));
100 assert!(output.contains("warning"));
101 assert!(output.contains("Pin versions"));
102 }
103}