Skip to content

[go-fan] Go Module Review: gojq #350

@github-actions

Description

@github-actions

🐹 Go Fan Report: gojq

Module Overview

gojq is a pure Go implementation of jq, the powerful JSON query and transformation language. It provides both a command-line tool and a Go library for parsing and executing jq queries, enabling JSON schema inference and transformation without external dependencies.

Current Version: v0.12.18 (latest, released Dec 1, 2025)
License: MIT
Stars: 3,666+
Maintenance: Active (last push 12 days ago)

Current Usage in gh-aw-mcpg

The project uses gojq in the jqschema middleware (internal/middleware/jqschema.go) to transform JSON responses into type schemas.

  • Files: 3 files (jqschema.go, jqschema_test.go, jqschema_integration_test.go)
  • Import Count: 1 import
  • Key APIs Used:
    • gojq.Parse(query) - Parse jq query strings
    • query.Run(input) - Execute queries against JSON data
    • Iterator pattern with iter.Next()

Current Pattern:

query, err := gojq.Parse(jqSchemaFilter)
iter := query.Run(jsonData)
v, ok := iter.Next()

This parses the same jq query on every request which is a significant performance bottleneck.

Research Findings

Recent Updates

v0.12.18 (Dec 1, 2025) - Latest release includes:

  • Performance improvements for long-running queries
  • Thread-safety fix: Stop numeric normalization for concurrent execution
  • Memory allocation optimizations
  • Array index limit increased to 536M
  • New functions: trimstr/1, toboolean/0
  • Improved gojq.NewIter as generic function

Best Practices from Maintainers

The gojq documentation strongly recommends a compile-once pattern for repeated queries:

"You can use gojq.Compile and code.Run to reuse the compiled code against multiple inputs to avoid compilation of the same query."

Key recommendations:

  1. Compile once, run many - Pre-compile queries at startup
  2. Use context - RunWithContext for timeout/cancellation
  3. Type-specific errors - Check for gojq.HaltError, ParseError
  4. Thread safety - v0.12.18 fixes ensure safe concurrent access to compiled code

Improvement Opportunities

🏃 Quick Wins

1. Compile Query Once (CRITICAL - High Impact, Low Effort)

Current Problem: Query is parsed on every request
Impact: 3-10x performance improvement
Effort: 10 minutes
Risk: Very low

Implementation:

var (
    jqSchemaCode *gojq.Code
    jqSchemaCompileErr error
)

func init() {
    query, err := gojq.Parse(jqSchemaFilter)
    if err != nil {
        jqSchemaCompileErr = fmt.Errorf("failed to parse jq schema filter: %w", err)
        return
    }
    jqSchemaCode, jqSchemaCompileErr = gojq.Compile(query)
}

func applyJqSchema(jsonData interface{}) (string, error) {
    if jqSchemaCompileErr != nil {
        return "", jqSchemaCompileErr
    }
    iter := jqSchemaCode.Run(jsonData)  // Reuse compiled code
    // ... rest
}

2. Add Context Support (Medium Impact, Low Effort)

Current Problem: No timeout/cancellation support
Impact: Better resource management, prevents runaway queries
Effort: 5 minutes
Risk: Very low

Implementation:

func applyJqSchema(ctx context.Context, jsonData interface{}) (string, error) {
    if jqSchemaCompileErr != nil {
        return "", jqSchemaCompileErr
    }
    iter := jqSchemaCode.RunWithContext(ctx, jsonData)
    // ... rest
}

3. Improve Error Handling (Low Impact, Low Effort)

Current Problem: Generic error checking
Impact: Better debugging experience
Effort: 15 minutes
Risk: Very low

Implementation:

if err, ok := v.(error); ok {
    if haltErr, ok := err.(*gojq.HaltError); ok && haltErr.Value() == nil {
        break  // Clean halt - no error
    }
    return "", fmt.Errorf("jq schema filter error: %w", err)
}

✨ Feature Opportunities

  1. Custom Functions for Schema Inference

    • Use gojq.WithFunction to add custom schema functions
    • Enable more sophisticated schema analysis
    • Reduce query complexity
  2. Performance Monitoring

    • Add metrics tracking query execution time
    • Alert on slow queries (>100ms)
    • Monitor memory usage patterns
  3. Query Validation at Startup

    • Compile all jq queries during initialization
    • Fail fast if queries are invalid
    • Better error messages at startup vs runtime
  4. Multiple Query Support

    • Pre-compile multiple schema strategies
    • Select query based on response type/size
    • Optimize for common patterns

📐 Best Practice Alignment

Aspect Current Recommended Benefit
Query Compilation Parse on every request Compile once at startup 3-10x performance
Context Support None Use RunWithContext Timeout handling
Error Handling Generic error check Type-specific checks Better debugging
Thread Safety Unknown Ensure safe concurrent access Reliability

🔧 General Improvements

  1. Add Benchmarks

    • Compare Parse+Run vs Compile+Run
    • Measure performance with various payload sizes
    • Establish performance baselines
  2. Documentation

    • Document why gojq was chosen
    • Explain query compilation strategy
    • Note performance characteristics
  3. Observability

    • Track schema transformation success/failure rates
    • Monitor execution time distribution
    • Log query performance anomalies

Recommendations

Priority Ranking

🚨 P0 - Implement Query Compilation (THIS WEEK)

Estimated effort: 10 minutes
Estimated impact: 3-10x performance improvement
Risk: Very low

This is a critical performance optimization that follows the library's documented best practices. The current implementation re-parses the query on every request, which is explicitly warned against in the gojq documentation.

Files to modify: internal/middleware/jqschema.go

P1 - Add Context Support (THIS WEEK)

Estimated effort: 5 minutes
Estimated impact: Better resource management
Risk: Very low

Add proper timeout/cancellation support using the request context.

Files to modify: internal/middleware/jqschema.go (function signature + 1 line change)

📊 P2 - Add Benchmarks (NEXT SPRINT)

Estimated effort: 30 minutes
Estimated impact: Validation of improvements
Risk: None

Quantify the performance improvements from P0/P1 changes.

Files to create: internal/middleware/jqschema_bench_test.go

🔍 P3 - Improve Error Handling (NEXT SPRINT)

Estimated effort: 15 minutes
Estimated impact: Better debugging
Risk: Very low

Next Steps

  1. Implement query compilation - Move to package init()
  2. Add context support - Update function signatures
  3. 📊 Add benchmarks - Measure performance gains
  4. 📝 Update documentation - Document performance characteristics
  5. 🧪 Test concurrent access - Ensure thread safety

References


Generated by Go Fan 🐹
Full module analysis saved to: docs/gojq-module-review.md
Review Date: 2026-01-19

AI generated by Go Fan

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions