From fca0951e5256731a1db25f373645f303910c8ce7 Mon Sep 17 00:00:00 2001 From: yusyus Date: Mon, 2 Feb 2026 22:04:56 +0300 Subject: [PATCH] fix: Handle JSON/YAML arrays at root level in config extraction PROBLEM: - Config extractor crashed on JSON files with arrays at root - Error: "'list' object has no attribute 'items'" - Example: save.json with [{"name": "item1"}, {"name": "item2"}] - Only handled dict roots, not list roots SOLUTION: - Added type checking in _parse_json() and _parse_yaml() - Handle three cases: 1. Dict at root: extract normally (existing behavior) 2. List at root: iterate and extract from each dict item 3. Primitive at root: skip with debug log - List items are prefixed with [index] in nested path CHANGES: - config_extractor.py _parse_json(): Added isinstance checks - config_extractor.py _parse_yaml(): Added list handling EXAMPLE: Before: WARNING: Error parsing save.json: 'list' object has no attribute 'items' After: Extracts settings with paths like "[0].name", "[1].value" IMPACT: - No more crashes on valid JSON/YAML arrays - Better coverage of config file variations - Handles game save files, API responses, data arrays Co-Authored-By: Claude Sonnet 4.5 --- src/skill_seekers/cli/config_extractor.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/skill_seekers/cli/config_extractor.py b/src/skill_seekers/cli/config_extractor.py index 876c2a1..de819e3 100644 --- a/src/skill_seekers/cli/config_extractor.py +++ b/src/skill_seekers/cli/config_extractor.py @@ -416,7 +416,18 @@ class ConfigParser: """Parse JSON configuration""" try: data = json.loads(config_file.raw_content) - self._extract_settings_from_dict(data, config_file) + + # Handle both dict and list at root level + if isinstance(data, dict): + self._extract_settings_from_dict(data, config_file) + elif isinstance(data, list): + # JSON array at root - extract from each dict item + for idx, item in enumerate(data): + if isinstance(item, dict): + self._extract_settings_from_dict(item, config_file, parent_path=[f"[{idx}]"]) + else: + # Primitive value at root (string, number, etc.) - skip + logger.debug(f"Skipping JSON with primitive root: {config_file.relative_path}") except json.JSONDecodeError as e: config_file.parse_errors.append(f"JSON parse error: {str(e)}") @@ -428,8 +439,15 @@ class ConfigParser: try: data = yaml.safe_load(config_file.raw_content) + + # Handle both dict and list at root level if isinstance(data, dict): self._extract_settings_from_dict(data, config_file) + elif isinstance(data, list): + # YAML array at root - extract from each dict item + for idx, item in enumerate(data): + if isinstance(item, dict): + self._extract_settings_from_dict(item, config_file, parent_path=[f"[{idx}]"]) except yaml.YAMLError as e: config_file.parse_errors.append(f"YAML parse error: {str(e)}")