schematic/config/formats/
json.rs

1use super::create_span;
2use crate::config::error::ConfigError;
3use crate::config::parser::ParserError;
4use crate::config::source::*;
5use miette::NamedSource;
6use serde::de::DeserializeOwned;
7use std::path::Path;
8
9#[derive(Default)]
10pub struct JsonFormat {}
11
12impl<T: DeserializeOwned> SourceFormat<T> for JsonFormat {
13    fn should_parse(&self, source: &Source) -> bool {
14        source
15            .get_file_ext()
16            .is_some_and(|ext| ext == "json" || ext == "jsonc")
17    }
18
19    fn parse(
20        &self,
21        source: &Source,
22        content: &str,
23        _cache_path: Option<&Path>,
24    ) -> Result<T, ConfigError> {
25        let mut content = String::from(if content.is_empty() { "{}" } else { content });
26
27        json_strip_comments::strip(&mut content).map_err(|error| {
28            ConfigError::JsonStripCommentsFailed {
29                file: source.get_file_name().to_owned(),
30                error: Box::new(error),
31            }
32        })?;
33
34        let de = &mut serde_json::Deserializer::from_str(&content);
35
36        let result: T = serde_path_to_error::deserialize(de).map_err(|error| ParserError {
37            content: NamedSource::new(source.get_file_name(), content.to_owned()),
38            path: error.path().to_string(),
39            span: Some(create_span(
40                &content,
41                error.inner().line(),
42                error.inner().column(),
43            )),
44            message: error.inner().to_string(),
45        })?;
46
47        Ok(result)
48    }
49}