json_schema_tools/
lint.rs

1use super::schema::SchemaFile;
2use serde_json::Value;
3
4#[derive(Debug)]
5pub enum Issue<'a> {
6    Json(serde_json::Error),
7    MisorderedKeys(super::key_order::KeyOrderMismatch<'a>),
8    UnrestrictedProperties(Vec<String>),
9    OptionalField(Vec<String>, String),
10    MisorderedRequires(Vec<String>),
11}
12
13pub fn lint(schema_file_value: &Value) -> Vec<Issue> {
14    let mut result = vec![];
15
16    for key_order_mismatch in super::key_order::check_key_order(schema_file_value) {
17        result.push(Issue::MisorderedKeys(key_order_mismatch));
18    }
19
20    match serde_json::from_value::<SchemaFile>(schema_file_value.clone()) {
21        Ok(schema_file) => {
22            for (path, object) in schema_file.objects() {
23                if !object.no_additional_properties() {
24                    result.push(Issue::UnrestrictedProperties(path.clone()));
25                }
26
27                let mut optional_fields = object.properties.keys().collect::<Vec<_>>();
28                optional_fields.retain(|value| !object.required.contains(value));
29
30                for optional_field in optional_fields {
31                    result.push(Issue::OptionalField(path.clone(), optional_field.clone()));
32                }
33
34                let mut required_fields = object.properties.keys().collect::<Vec<_>>();
35                required_fields.retain(|value| object.required.contains(value));
36
37                if required_fields != object.required.iter().collect::<Vec<_>>() {
38                    result.push(Issue::MisorderedRequires(path.clone()));
39                }
40            }
41        }
42        Err(error) => {
43            result.push(Issue::Json(error));
44        }
45    }
46
47    result
48}