Skip to content

Commit 1e13d50

Browse files
committed
integrate codegen in CLI
1 parent 96a7eb2 commit 1e13d50

3 files changed

Lines changed: 119 additions & 8 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
temp/
33
venv/
44
__pycache__/
5+
*.egg-info/

json_explorer/cli.py

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from .stats import DataStatsAnalyzer
66
from .visualizer import JSONVisualizer
77
from .filter_parser import FilterExpressionParser
8+
from .analyzer import analyze_json
9+
from .codegen import MultiTargetGenerator, parse_config_string
810

911

1012
class CLIHandler:
@@ -26,7 +28,7 @@ def set_data(self, data, source):
2628
def run(self, args):
2729
"""Run CLI mode operations based on arguments."""
2830
if not self.data:
29-
self.console.print(" [red]No data loaded[/red]")
31+
self.console.print(" [red]No data loaded[/red]")
3032
return 1
3133

3234
self.console.print(f"📄 Loaded: {self.source}")
@@ -47,6 +49,10 @@ def run(self, args):
4749
if args.plot:
4850
self._handle_visualization(args)
4951

52+
# Code generation
53+
if args.codegen:
54+
self._handle_codegen(args)
55+
5056
return 0
5157

5258
def _handle_tree_display(self, tree_type):
@@ -80,7 +86,7 @@ def _handle_search(self, args):
8086
elif args.search_type == "pair":
8187
if not args.search_value:
8288
self.console.print(
83-
" [red]--search-value required for pair search[/red]"
89+
" [red]--search-value required for pair search[/red]"
8490
)
8591
return
8692
results = self.searcher.search_key_value_pairs(
@@ -91,10 +97,10 @@ def _handle_search(self, args):
9197
filter_func = FilterExpressionParser.parse_filter(search_term)
9298
results = self.searcher.search_with_filter(self.data, filter_func)
9399
except Exception as e:
94-
self.console.print(f" [red]Filter error: {e}[/red]")
100+
self.console.print(f" [red]Filter error: {e}[/red]")
95101
return
96102
else:
97-
self.console.print(f" [red]Unknown search type: {args.search_type}[/red]")
103+
self.console.print(f" [red]Unknown search type: {args.search_type}[/red]")
98104
return
99105

100106
# Display results
@@ -134,4 +140,72 @@ def _handle_visualization(self, args):
134140
"✅ [green]Visualizations generated successfully[/green]"
135141
)
136142
except Exception as e:
137-
self.console.print(f"❌ [red]Visualization error: {e}[/red]")
143+
self.console.print(f"⌛ [red]Visualization error: {e}[/red]")
144+
145+
def _handle_codegen(self, args):
146+
"""Handle code generation."""
147+
self.console.print("\n🔧 Generating code from JSON schema...")
148+
149+
try:
150+
# Analyze JSON to generate schema
151+
schema = analyze_json(self.data)
152+
153+
# Create generator
154+
root_name = getattr(args, "codegen_root", "Root")
155+
generator = MultiTargetGenerator(schema, root_name=root_name)
156+
157+
# Parse configuration if provided
158+
config_dict = {}
159+
if hasattr(args, "codegen_config") and args.codegen_config:
160+
config_dict = parse_config_string(args.codegen_config)
161+
162+
# Handle target selection
163+
if args.codegen == "all":
164+
# Generate all targets
165+
self.console.print("📝 Generating code for all supported targets...")
166+
results = generator.generate_all(config_dict)
167+
168+
for target, code in results.items():
169+
self.console.print(f"\n{'='*60}")
170+
self.console.print(
171+
f"🎯 [bold cyan]TARGET: {target.upper()}[/bold cyan]"
172+
)
173+
self.console.print("=" * 60)
174+
print(code)
175+
176+
self.console.print(
177+
f"\n✅ [green]Generated code for {len(results)} targets[/green]"
178+
)
179+
180+
elif args.codegen in generator.list_targets():
181+
# Generate specific target
182+
self.console.print(f"📝 Generating {args.codegen.upper()} code...")
183+
code = generator.generate(args.codegen, config_dict)
184+
185+
self.console.print(
186+
f"\n🎯 [bold cyan]{args.codegen.upper()} Code:[/bold cyan]"
187+
)
188+
self.console.print("-" * 50)
189+
print(code)
190+
191+
self.console.print(f"\n✅ [green]Code generated successfully[/green]")
192+
193+
else:
194+
available = ", ".join(generator.list_targets())
195+
self.console.print(f"⌛ [red]Unknown target: {args.codegen}[/red]")
196+
self.console.print(
197+
f"[yellow]Available targets: {available}, all[/yellow]"
198+
)
199+
200+
except Exception as e:
201+
self.console.print(f"⌛ [red]Code generation error: {e}[/red]")
202+
203+
def list_codegen_targets(self):
204+
"""List available code generation targets."""
205+
generator = MultiTargetGenerator({})
206+
targets = generator.list_targets()
207+
208+
self.console.print("\n🎯 [bold]Available Code Generation Targets:[/bold]")
209+
for target in targets:
210+
self.console.print(f" • [cyan]{target}[/cyan]")
211+
self.console.print(" • [cyan]all[/cyan] - Generate code for all targets")

json_explorer/main.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,16 @@ def load_data(self, file_path=None, url=None):
3737
self.source, self.data = load_json(file_path, url)
3838
return True
3939
except Exception as e:
40-
self.console.print(f" [red]Error loading data: {e}[/red]")
40+
self.console.print(f" [red]Error loading data: {e}[/red]")
4141
return False
4242

4343
def run(self, args):
4444
"""Main execution method."""
45+
# Handle special commands that don't require data
46+
if args.list_codegen_targets:
47+
self.cli_handler.list_codegen_targets()
48+
return 0
49+
4550
if not self.load_data(args.file, args.url):
4651
return 1
4752

@@ -55,7 +60,7 @@ def run(self, args):
5560

5661
def _has_cli_actions(self, args) -> bool:
5762
"""Check if any CLI-specific actions are requested."""
58-
return any([args.tree, args.search, args.stats, args.plot])
63+
return any([args.tree, args.search, args.stats, args.plot, args.codegen])
5964

6065

6166
def create_parser():
@@ -70,6 +75,8 @@ def create_parser():
7075
%(prog)s data.json --search "name" --search-type key
7176
%(prog)s data.json --search "isinstance(value, int) and value > 10" --search-type filter
7277
%(prog)s --url https://api.example.com/data --plot --tree-results
78+
%(prog)s data.json --codegen java --codegen-root User --codegen-config "lombok=true,jackson=true"
79+
%(prog)s data.json --codegen all --codegen-root ApiResponse
7380
""",
7481
)
7582

@@ -150,6 +157,30 @@ def create_parser():
150157
help="Don't open browser for HTML visualizations",
151158
)
152159

160+
# Code generation options
161+
codegen_group = parser.add_argument_group("code generation options")
162+
codegen_group.add_argument(
163+
"--codegen",
164+
type=str,
165+
help="Generate code for target language (java, python, typescript, go, rust, openapi, graphql, all)",
166+
)
167+
codegen_group.add_argument(
168+
"--codegen-root",
169+
type=str,
170+
default="Root",
171+
help="Root class/type name for generated code (default: Root)",
172+
)
173+
codegen_group.add_argument(
174+
"--codegen-config",
175+
type=str,
176+
help="Code generation configuration (key=value,key2=value2). Example: lombok=true,jackson=true,package=com.example",
177+
)
178+
codegen_group.add_argument(
179+
"--list-codegen-targets",
180+
action="store_true",
181+
help="List all available code generation targets",
182+
)
183+
153184
return parser
154185

155186

@@ -162,8 +193,13 @@ def main():
162193
parser.print_help()
163194
return 1
164195

196+
# Handle special commands that don't need file/url
197+
if args.list_codegen_targets:
198+
explorer = JSONExplorer()
199+
return explorer.run(args)
200+
165201
if not (args.file or args.url):
166-
print(" Error: You must provide a file path or --url")
202+
print(" Error: You must provide a file path or --url")
167203
parser.print_help()
168204
return 1
169205

0 commit comments

Comments
 (0)