Spaces:
Runtime error
Runtime error
"""This module contains functions to fix JSON strings using general programmatic approaches, suitable for addressing | |
common JSON formatting issues.""" | |
from __future__ import annotations | |
import contextlib | |
import json | |
import re | |
from typing import Optional | |
from autogpt.config import Config | |
from autogpt.json_utils.utilities import extract_char_position | |
CFG = Config() | |
def fix_invalid_escape(json_to_load: str, error_message: str) -> str: | |
"""Fix invalid escape sequences in JSON strings. | |
Args: | |
json_to_load (str): The JSON string. | |
error_message (str): The error message from the JSONDecodeError | |
exception. | |
Returns: | |
str: The JSON string with invalid escape sequences fixed. | |
""" | |
while error_message.startswith("Invalid \\escape"): | |
bad_escape_location = extract_char_position(error_message) | |
json_to_load = ( | |
json_to_load[:bad_escape_location] + json_to_load[bad_escape_location + 1 :] | |
) | |
try: | |
json.loads(json_to_load) | |
return json_to_load | |
except json.JSONDecodeError as e: | |
if CFG.debug_mode: | |
print("json loads error - fix invalid escape", e) | |
error_message = str(e) | |
return json_to_load | |
def balance_braces(json_string: str) -> Optional[str]: | |
""" | |
Balance the braces in a JSON string. | |
Args: | |
json_string (str): The JSON string. | |
Returns: | |
str: The JSON string with braces balanced. | |
""" | |
open_braces_count = json_string.count("{") | |
close_braces_count = json_string.count("}") | |
while open_braces_count > close_braces_count: | |
json_string += "}" | |
close_braces_count += 1 | |
while close_braces_count > open_braces_count: | |
json_string = json_string.rstrip("}") | |
close_braces_count -= 1 | |
with contextlib.suppress(json.JSONDecodeError): | |
json.loads(json_string) | |
return json_string | |
def add_quotes_to_property_names(json_string: str) -> str: | |
""" | |
Add quotes to property names in a JSON string. | |
Args: | |
json_string (str): The JSON string. | |
Returns: | |
str: The JSON string with quotes added to property names. | |
""" | |
def replace_func(match: re.Match) -> str: | |
return f'"{match[1]}":' | |
property_name_pattern = re.compile(r"(\w+):") | |
corrected_json_string = property_name_pattern.sub(replace_func, json_string) | |
try: | |
json.loads(corrected_json_string) | |
return corrected_json_string | |
except json.JSONDecodeError as e: | |
raise e | |
def correct_json(json_to_load: str) -> str: | |
""" | |
Correct common JSON errors. | |
Args: | |
json_to_load (str): The JSON string. | |
""" | |
try: | |
if CFG.debug_mode: | |
print("json", json_to_load) | |
json.loads(json_to_load) | |
return json_to_load | |
except json.JSONDecodeError as e: | |
if CFG.debug_mode: | |
print("json loads error", e) | |
error_message = str(e) | |
if error_message.startswith("Invalid \\escape"): | |
json_to_load = fix_invalid_escape(json_to_load, error_message) | |
if error_message.startswith( | |
"Expecting property name enclosed in double quotes" | |
): | |
json_to_load = add_quotes_to_property_names(json_to_load) | |
try: | |
json.loads(json_to_load) | |
return json_to_load | |
except json.JSONDecodeError as e: | |
if CFG.debug_mode: | |
print("json loads error - add quotes", e) | |
error_message = str(e) | |
if balanced_str := balance_braces(json_to_load): | |
return balanced_str | |
return json_to_load | |