fix json export

This commit is contained in:
VALLONGOL 2025-06-24 08:06:17 +02:00
parent 01b30ccfb2
commit b8eb3ce9ad

View File

@ -6,12 +6,13 @@ Orchestrates the interaction between the GUI and the core processing logic.
"""
import multiprocessing as mp
import csv
import json
import os
import subprocess
import sys
from pathlib import Path
from typing import List, Any, Dict, Tuple, Optional
from tkinter import filedialog
from tkinter import filedialog, messagebox
import tkinter as tk
from ..utils.config_manager import ConfigManager
@ -46,10 +47,6 @@ def _get_value_from_path(batch: DataBatch, field: ExportField) -> Any:
log.warning(f"Could not find attribute for path: {path}")
return "N/A"
def _write_json_row(file_handle, row_dict: Dict[str, Any]):
# Helper to write a JSON object to a file, followed by a newline.
json.dump(row_dict, file_handle)
file_handle.write("\n")
class AppController:
"""The main controller of the application."""
@ -66,6 +63,9 @@ class AppController:
self.output_file_handles: Dict[str, Any] = {}
self.csv_writers: Dict[str, Any] = {}
# Buffer for JSON data
self.json_data_buffer: List[Dict[str, Any]] = []
self.last_generated_out_file: Optional[Path] = None
def bind_view(self, view):
@ -132,10 +132,13 @@ class AppController:
self.output_file_handles.clear()
self.csv_writers.clear()
self.active_export_profiles.clear()
self.json_data_buffer.clear() # Clear JSON buffer
try:
output_dir = Path(self.view.out_output_dir_var.get())
basename = self.view.out_basename_var.get()
profiles = self.config_manager.get_export_profiles()
if self.view.out_output_csv_var.get():
profile = next((p for p in profiles if p.name == self.view.out_csv_profile_var.get()), None)
if not profile: raise ValueError(f"CSV profile '{self.view.out_csv_profile_var.get()}' not found.")
@ -145,12 +148,13 @@ class AppController:
self.output_file_handles["csv"] = fh
self.csv_writers["csv"] = csv.writer(fh)
self.csv_writers["csv"].writerow([f.column_name for f in profile.fields])
if self.view.out_output_json_var.get():
profile = next((p for p in profiles if p.name == self.view.out_json_profile_var.get()), None)
if not profile: raise ValueError(f"JSON profile '{self.view.out_json_profile_var.get()}' not found.")
self.active_export_profiles["json"] = profile
path = (output_dir / basename).with_suffix(".json")
self.output_file_handles["json"] = open(path, "w", encoding="utf-8")
# JSON file is no longer opened here, it's written at the end.
return True
except (IOError, ValueError) as e:
log.error(f"Failed to prepare output files: {e}")
@ -175,7 +179,6 @@ class AppController:
self.config_manager.set("active_out_export_profile_name", self.view.out_csv_profile_var.get())
self.config_manager.save_config()
# --- CORRECTED LINE ---
active_profile = self.active_export_profiles.get("csv") or self.active_export_profiles.get("json")
worker_args = (Path(filepath_str), self.command_queue, self.result_queue, active_profile)
self._launch_worker(run_worker_process, worker_args)
@ -213,7 +216,7 @@ class AppController:
output_dir = self.view.rec_output_dir_var.get()
except ValueError as e:
log.error(f"Configuration error: {e}")
tk.messagebox.showerror("Configuration Error", str(e), parent=self.view)
messagebox.showerror("Configuration Error", str(e), parent=self.view)
return
self.is_processing = True
@ -241,20 +244,42 @@ class AppController:
self.csv_writers.clear()
def handle_data_batch(self, batch: DataBatch):
"""Writes a data batch to the currently open output files (CSV/JSON)."""
"""Writes a data batch to CSV and buffers it for JSON."""
if self.csv_writers.get("csv"):
profile = self.active_export_profiles["csv"]
row_values = [_get_value_from_path(batch, field) for field in profile.fields]
self.csv_writers["csv"].writerow(row_values)
if self.output_file_handles.get("json"):
if "json" in self.active_export_profiles:
profile = self.active_export_profiles["json"]
row_dict = {field.column_name: _get_value_from_path(batch, field) for field in profile.fields}
_write_json_row(self.output_file_handles["json"], row_dict)
self.json_data_buffer.append(row_dict)
if batch.batch_id % 20 == 0:
for fh in self.output_file_handles.values():
fh.flush()
if "csv" in self.output_file_handles:
self.output_file_handles["csv"].flush()
def _write_json_buffer_to_file(self):
"""Writes the buffered JSON data to a file."""
if not self.json_data_buffer:
if "json" in self.active_export_profiles:
log.info("JSON export was enabled, but no data batches were generated. Skipping file creation.")
return
try:
output_dir = Path(self.view.out_output_dir_var.get())
basename = self.view.out_basename_var.get()
path = (output_dir / basename).with_suffix(".json")
log.info(f"Writing {len(self.json_data_buffer)} records to JSON file: {path}")
with open(path, "w", encoding="utf-8") as f:
json.dump(self.json_data_buffer, f, indent=4)
log.info("JSON file written successfully.")
except (IOError, ValueError) as e:
log.error(f"Failed to write JSON output file: {e}")
finally:
self.json_data_buffer.clear()
def open_folder_from_path(self, folder_path_str: str):
if not folder_path_str: return
@ -270,6 +295,11 @@ class AppController:
def handle_worker_completion(self, msg: Dict[str, Any]):
status = "Interrupted" if msg.get("interrupted") else "Complete"
log.info(f"--- Process {status}. ---")
# Write buffered JSON data before closing files
if self.view.out_output_json_var.get():
self._write_json_buffer_to_file()
self._close_all_files()
self.is_processing = False
self.worker_process = None