Last active
December 30, 2025 04:00
-
-
Save kristovatlas/824d0d74ac169cfd7b8810bb27143324 to your computer and use it in GitHub Desktop.
Prettify JSON-y looking things locally
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import ast | |
| import json | |
| import sys | |
| def parse_nested_json(obj): | |
| """Recursively parse any string values that are valid JSON into objects.""" | |
| if isinstance(obj, dict): | |
| return {k: parse_nested_json(v) for k, v in obj.items()} | |
| elif isinstance(obj, list): | |
| return [parse_nested_json(i) for i in obj] | |
| elif isinstance(obj, str): | |
| try: | |
| parsed = json.loads(obj) | |
| return parse_nested_json(parsed) # Recurse if nested | |
| except json.JSONDecodeError: | |
| return obj # Not JSON, leave as string | |
| else: | |
| return obj | |
| def parse_relaxed_json(input_path, output_path=None, indent=4, sort_keys=False): | |
| try: | |
| with open(input_path, 'r') as f: | |
| data_str = f.read() | |
| data = ast.literal_eval(data_str) # Parses with single quotes allowed | |
| # Recursively parse nested JSON strings | |
| expanded_data = parse_nested_json(data) | |
| pretty_json = json.dumps(expanded_data, indent=indent, sort_keys=sort_keys) | |
| if output_path: | |
| with open(output_path, 'w') as f: | |
| f.write(pretty_json) | |
| print(f"Prettified JSON saved to {output_path}") | |
| else: | |
| print(pretty_json) | |
| except SyntaxError as e: | |
| print(f"Error: Invalid syntax for literal eval - {e}") | |
| except ValueError as e: | |
| print(f"Error: Malformed data - {e}") | |
| except FileNotFoundError: | |
| print(f"Error: File '{input_path}' not found") | |
| if __name__ == "__main__": | |
| if len(sys.argv) < 2: | |
| print("Usage: python parse_relaxed_json.py input.json [output.json]") | |
| sys.exit(1) | |
| input_path = sys.argv[1] | |
| output_path = sys.argv[2] if len(sys.argv) > 2 else None | |
| parse_relaxed_json(input_path, output_path) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import pprint | |
| import importlib | |
| import sys | |
| def dynamic_eval(text): | |
| """ | |
| Dynamically evaluates the Python expression in the text, importing modules as needed. | |
| WARNING: This uses eval, which can be dangerous if the text is not trusted. | |
| Use only with text from reliable sources. | |
| """ | |
| # Start with full builtins; for safety, you could restrict them | |
| globs = {'__builtins__': __builtins__} | |
| max_attempts = 20 # Prevent infinite loops, adjust as needed | |
| attempts = 0 | |
| while attempts < max_attempts: | |
| try: | |
| return eval(text, globs) | |
| except NameError as e: | |
| # Extract the missing name | |
| import re | |
| match = re.search(r"name '(\w+)' is not defined", str(e)) | |
| if match: | |
| missing_name = match.group(1) | |
| else: | |
| raise | |
| try: | |
| module = importlib.import_module(missing_name) | |
| globs[missing_name] = module | |
| except ImportError: | |
| raise ValueError(f"Cannot import {missing_name}. It may not be a standard module or requires installation.") | |
| attempts += 1 | |
| raise ValueError("Max attempts reached. Possible cyclic dependencies or complex issues.") | |
| def pretty_print_python_output_from_file(filename): | |
| """ | |
| Reads the printed Python text from a file, parses it using dynamic_eval, and pretty-prints it. | |
| :param filename: The path to the file containing the output from print() in Python. | |
| :return: Pretty-printed string or error message. | |
| """ | |
| try: | |
| with open(filename, 'r', encoding='utf-8') as file: | |
| text = file.read().strip() | |
| except Exception as e: | |
| return f"Error reading the file: {str(e)}" | |
| try: | |
| obj = dynamic_eval(text) | |
| except Exception as e: | |
| return f"Error parsing the text: {str(e)}" | |
| # Pretty-print the object with indentation | |
| return pprint.pformat(obj, indent=4, width=80) | |
| # Example usage via command line | |
| if __name__ == "__main__": | |
| if len(sys.argv) < 2: | |
| print("Usage: python script.py input_file [output_file]") | |
| sys.exit(1) | |
| input_file = sys.argv[1] | |
| output_file = sys.argv[2] if len(sys.argv) > 2 else None | |
| result = pretty_print_python_output_from_file(input_file) | |
| if output_file: | |
| try: | |
| with open(output_file, 'w', encoding='utf-8') as f: | |
| f.write(result + '\n') | |
| except Exception as e: | |
| print(f"Error writing to output file: {str(e)}") | |
| else: | |
| print(result) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment