Skip to main content

pedant_core/
json_format.rs

1use serde::Serialize;
2
3use crate::violation::{Severity, Violation};
4
5/// Flat JSON representation of a violation for `--format json` output.
6#[derive(Serialize)]
7pub struct JsonViolation<'a> {
8    r#type: &'a str,
9    check: &'static str,
10    category: &'static str,
11    severity: Severity,
12    file: &'a str,
13    line: usize,
14    column: usize,
15    message: &'a str,
16    fix: &'static str,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pattern: Option<&'a str>,
19    #[serde(skip_serializing_if = "Option::is_none")]
20    subject: Option<&'a str>,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    expected: Option<&'a str>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    observed: Option<&'a str>,
25}
26
27impl<'a> From<&'a Violation> for JsonViolation<'a> {
28    fn from(v: &'a Violation) -> Self {
29        let detail = v.violation_type.visibility_detail();
30        Self {
31            r#type: v.violation_type.code(),
32            check: v.violation_type.code(),
33            category: v.violation_type.category(),
34            severity: v.severity,
35            file: &*v.file_path,
36            line: v.line,
37            column: v.column,
38            message: &*v.message,
39            fix: v.violation_type.rationale().fix,
40            pattern: v.violation_type.pattern(),
41            subject: detail.map(|d| &*d.subject),
42            expected: detail.map(|d| &*d.expected),
43            observed: detail.map(|d| &*d.observed),
44        }
45    }
46}