69 lines
2.1 KiB
Python
69 lines
2.1 KiB
Python
import json
|
|
from json import JSONDecodeError
|
|
from types import SimpleNamespace
|
|
from pathlib import Path
|
|
from typing import Any, Optional, Union
|
|
|
|
|
|
class JsonFileLoader:
|
|
"""
|
|
Carrega arquivos JSON e retorna como objeto (SimpleNamespace) ou dict.
|
|
Retorna None quando não houver arquivo ou dados.
|
|
"""
|
|
|
|
def __init__(self, file_path: Union[str, Path], encoding: str = "utf-8"):
|
|
self.path = Path(file_path)
|
|
self.encoding = encoding
|
|
|
|
def load(
|
|
self, as_namespace: bool = True, empty_as_none: bool = True
|
|
) -> Optional[Any]:
|
|
"""
|
|
Lê o JSON do disco.
|
|
- as_namespace=True: retorna SimpleNamespace (com conversão recursiva).
|
|
- as_namespace=False: retorna dict/list nativos.
|
|
- empty_as_none=True: {}, [] ou None são tratados como "sem dados" e retornam None.
|
|
"""
|
|
# 1) Arquivo inexistente ou não regular
|
|
if not self.path.exists() or not self.path.is_file():
|
|
return None
|
|
|
|
# 2) Arquivo vazio
|
|
if self.path.stat().st_size == 0:
|
|
return None
|
|
|
|
# 3) Leitura + limpeza
|
|
try:
|
|
with self.path.open("r", encoding=self.encoding) as f:
|
|
raw = f.read()
|
|
except OSError:
|
|
return None
|
|
|
|
raw = (raw or "").strip()
|
|
if not raw:
|
|
return None
|
|
|
|
# 4) Parse do JSON
|
|
try:
|
|
data = json.loads(raw)
|
|
except JSONDecodeError:
|
|
return None
|
|
|
|
# 5) Tratar dados vazios
|
|
if empty_as_none and (data is None or data == {} or data == []):
|
|
return None
|
|
|
|
# 6) Converter (opcional) para SimpleNamespace
|
|
return self._to_namespace(data) if as_namespace else data
|
|
|
|
# ---------- helpers ----------
|
|
@classmethod
|
|
def _to_namespace(cls, value: Any) -> Any:
|
|
"""Converte recursivamente dict/list em SimpleNamespace/list."""
|
|
if isinstance(value, dict):
|
|
return SimpleNamespace(
|
|
**{k: cls._to_namespace(v) for k, v in value.items()}
|
|
)
|
|
if isinstance(value, list):
|
|
return [cls._to_namespace(v) for v in value]
|
|
return value
|