1use super::traits::{ContentParser, ContentType, ParsedContent};
4use crate::error::Result;
5
6pub struct JsonParser;
8
9impl JsonParser {
10 pub fn new() -> Self {
12 Self
13 }
14
15 pub fn parse_value(content: &str) -> Option<serde_json::Value> {
17 serde_json::from_str(content).ok()
18 }
19}
20
21impl Default for JsonParser {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl ContentParser for JsonParser {
28 fn parse(&self, content: &str, path: &str) -> Result<ParsedContent> {
29 let mut parsed =
30 ParsedContent::new(ContentType::Json, content.to_string(), path.to_string());
31
32 if let Some(value) = Self::parse_value(content) {
34 parsed = parsed.with_structured_data(value);
35 }
36
37 Ok(parsed)
38 }
39
40 fn supported_extensions(&self) -> &[&str] {
41 &[".json"]
42 }
43
44 fn can_parse(&self, path: &str) -> bool {
45 let path_lower = path.to_lowercase();
46 path_lower.ends_with(".json")
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_parse_valid_json() {
56 let parser = JsonParser::new();
57 let content = r#"{"name": "test", "version": "1.0"}"#;
58 let result = parser.parse(content, "config.json").unwrap();
59
60 assert_eq!(result.content_type, ContentType::Json);
61 assert!(result.structured_data.is_some());
62 let data = result.structured_data.unwrap();
63 assert_eq!(data["name"].as_str(), Some("test"));
64 }
65
66 #[test]
67 fn test_parse_invalid_json() {
68 let parser = JsonParser::new();
69 let content = "not valid json";
70 let result = parser.parse(content, "config.json").unwrap();
71
72 assert_eq!(result.content_type, ContentType::Json);
73 assert!(result.structured_data.is_none());
74 }
75
76 #[test]
77 fn test_supported_extensions() {
78 let parser = JsonParser::new();
79 assert!(parser.can_parse("mcp.json"));
80 assert!(parser.can_parse("package.json"));
81 assert!(!parser.can_parse("config.yaml"));
82 }
83
84 #[test]
85 fn test_parse_complex_json() {
86 let parser = JsonParser::new();
87 let content = r#"{
88 "mcpServers": {
89 "example": {
90 "command": "npx",
91 "args": ["-y", "@example/mcp-server"]
92 }
93 }
94 }"#;
95 let result = parser.parse(content, "mcp.json").unwrap();
96
97 assert!(result.structured_data.is_some());
98 let data = result.structured_data.unwrap();
99 assert!(data["mcpServers"]["example"]["command"].is_string());
100 }
101}