Coverage for lintro / formatters / styles / json.py: 100%

23 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""JSON output style implementation.""" 

2 

3import json 

4from datetime import datetime 

5from typing import Any 

6 

7from lintro.formatters.core.format_registry import OutputStyle 

8 

9 

10class JsonStyle(OutputStyle): 

11 """Output format that renders data as structured JSON.""" 

12 

13 def format( 

14 self, 

15 columns: list[str], 

16 rows: list[list[Any]], 

17 tool_name: str | None = None, 

18 **kwargs: Any, 

19 ) -> str: 

20 """Format a table given columns and rows as structured JSON. 

21 

22 Args: 

23 columns: List of column names. 

24 rows: List of row values (each row is a list of cell values). 

25 tool_name: Name of the tool that generated the data. 

26 **kwargs: Additional metadata; `metadata` can be provided here. 

27 

28 Returns: 

29 Formatted data as structured JSON string. 

30 """ 

31 metadata: dict[str, Any] | None = kwargs.pop("metadata", None) 

32 # Convert column names to standardized format 

33 normalized_columns = [col.lower().replace(" ", "_") for col in columns] 

34 

35 # Convert rows to list of dictionaries with proper data types 

36 issues: list[dict[str, Any]] = [] 

37 for row in rows: 

38 issue_dict: dict[str, Any] = {} 

39 for i, value in enumerate(row): 

40 if i < len(normalized_columns): 

41 issue_dict[normalized_columns[i]] = value 

42 issues.append(issue_dict) 

43 

44 # Create the final JSON structure 

45 result: dict[str, Any] = { 

46 "tool": tool_name, 

47 "timestamp": datetime.now().isoformat(), 

48 "total_issues": len(issues), 

49 "issues": issues, 

50 } 

51 

52 # Add metadata if provided 

53 if metadata: 

54 result["metadata"] = metadata 

55 

56 # Add any additional kwargs as metadata 

57 if kwargs: 

58 if "metadata" not in result: 

59 result["metadata"] = {} 

60 result["metadata"].update(kwargs) 

61 

62 return json.dumps(result, indent=2, ensure_ascii=False)