100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Скрипт объединения нескольких JSON-файлов в один.
|
||
|
||
Файлы должны лежать в том же каталоге, что и скрипт. Каждый файл — один JSON-объект;
|
||
результат — один объект, собранный из верхнеуровневых ключей всех файлов.
|
||
При совпадении ключей побеждает значение из файла, идущего позже в списке.
|
||
"""
|
||
|
||
import argparse
|
||
import json
|
||
from pathlib import Path
|
||
|
||
|
||
def get_script_dir() -> Path:
|
||
"""Возвращает каталог, в котором расположен скрипт."""
|
||
return Path(__file__).resolve().parent
|
||
|
||
|
||
def merge_json_files(
|
||
filenames: list[str],
|
||
base_dir: Path,
|
||
output_path: Path,
|
||
indent: int | None = 2,
|
||
) -> None:
|
||
"""
|
||
Читает перечисленные JSON-файлы из base_dir и записывает объединённый объект в output_path.
|
||
|
||
Args:
|
||
filenames: Список имён файлов (без пути).
|
||
base_dir: Каталог с входными файлами.
|
||
output_path: Полный путь к результирующему JSON-файлу.
|
||
indent: Отступ для форматирования JSON (по умолчанию 2).
|
||
|
||
Raises:
|
||
FileNotFoundError: Если какой-либо входной файл не найден.
|
||
json.JSONDecodeError: Если содержимое файла не является валидным JSON.
|
||
"""
|
||
result: dict = {}
|
||
|
||
for name in filenames:
|
||
path = base_dir / name
|
||
if not path.is_file():
|
||
raise FileNotFoundError(f"Файл не найден: {path}")
|
||
|
||
with open(path, "r", encoding="utf-8") as f:
|
||
data = json.load(f)
|
||
|
||
if not isinstance(data, dict):
|
||
raise TypeError(
|
||
f"Файл {name} должен содержать JSON-объект (dict), получен: {type(data).__name__}"
|
||
)
|
||
result.update(data)
|
||
|
||
with open(output_path, "w", encoding="utf-8") as f:
|
||
json.dump(result, f, ensure_ascii=False, indent=indent)
|
||
|
||
|
||
def main() -> None:
|
||
"""Точка входа: разбор аргументов и вызов объединения."""
|
||
script_dir = get_script_dir()
|
||
|
||
parser = argparse.ArgumentParser(
|
||
description="Объединить несколько JSON-файлов из каталога скрипта в один файл."
|
||
)
|
||
parser.add_argument(
|
||
"files",
|
||
nargs="+",
|
||
metavar="FILE",
|
||
help="Имена JSON-файлов (в каталоге скрипта)",
|
||
)
|
||
parser.add_argument(
|
||
"-o",
|
||
"--output",
|
||
default="merged.json",
|
||
metavar="OUTPUT",
|
||
help="Имя результирующего файла (по умолчанию: merged.json)",
|
||
)
|
||
parser.add_argument(
|
||
"--no-indent",
|
||
action="store_true",
|
||
help="Не форматировать вывод (компактный JSON)",
|
||
)
|
||
args = parser.parse_args()
|
||
|
||
output_path = script_dir / args.output
|
||
indent = None if args.no_indent else 2
|
||
|
||
merge_json_files(
|
||
filenames=args.files,
|
||
base_dir=script_dir,
|
||
output_path=output_path,
|
||
indent=indent,
|
||
)
|
||
print(f"Записано: {output_path}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|