/ src / utils / json_loader.py
json_loader.py
 1  """JSON file loading utilities."""
 2  
 3  from __future__ import annotations
 4  
 5  import json
 6  import logging
 7  from pathlib import Path
 8  from typing import Any
 9  
10  logger = logging.getLogger(__name__)
11  
12  
13  def load_json_file(file_path: Path | str | None) -> dict[str, Any] | None:
14      """Load a JSON file safely with proper error handling.
15  
16      Parameters
17      ----------
18      file_path
19          Path to the JSON file. Can be None, in which case None is returned.
20  
21      Returns
22      -------
23      dict[str, Any] | None
24          Parsed JSON data as a dictionary, or None if:
25          - file_path is None
26          - File doesn't exist
27          - File can't be parsed as JSON
28          - JSON root is not a dictionary
29      """
30      if file_path is None:
31          return None
32  
33      try:
34          path = Path(file_path).expanduser().resolve()
35  
36          if not path.exists():
37              logger.warning(f"JSON file not found: {path}")
38              return None
39  
40          with path.open() as f:
41              data = json.load(f)
42  
43          if not isinstance(data, dict):
44              logger.error(f"Invalid JSON format: expected dict, got {type(data).__name__}")
45              return None
46  
47          return data
48  
49      except json.JSONDecodeError as e:
50          raise ValueError(f"Failed to parse JSON file '{file_path}': {e}") from e
51      except Exception as e:
52          raise ValueError(f"Failed to load JSON file '{file_path}': {e}") from e