-
Notifications
You must be signed in to change notification settings - Fork 19
[go-fan] Go Module Review: gojq (github.com/itchyny/gojq)Β #3111
Description
πΉ Go Fan Report: gojq
Module Overview
github.com/itchyny/gojq is a pure Go implementation of jq β the JSON query and transformation language. It provides both a CLI and a Go library with full jq compatibility, plus Go-native extensions like context cancellation, custom functions, and custom types. The project currently uses v0.12.18; v0.12.19 is now available.
Current Usage in gh-aw-mcpg
gojq powers the large payload middleware (internal/middleware/jqschema.go). When a backend MCP tool response exceeds the configured sizeThreshold, the middleware:
- Saves the full JSON payload to disk (
payload.json) - Runs a jq schema-inference filter that replaces leaf values with their type names (
"string","number", etc.) and collapses arrays to a single representative element - Returns a lightweight metadata response to the client containing the schema, a preview, and the file path
- Files: 2 (+ 1 bench test file)
- Key APIs Used:
gojq.Parse,gojq.Compile,(*Code).RunWithContext,*gojq.HaltError - Pattern: pre-compiled query code (compile once at
init(), reuse per request)
Research Findings
The project already follows gojq's recommended best practices quite well. The benchmarks in jqschema_bench_test.go demonstrate a 10β100x speedup from pre-compiling vs parsing on every request, and the implementation correctly uses RunWithContext for cancellation.
Recent Updates (v0.12.18βv0.12.19)
- v0.12.19 is the latest release (observed via GitHub release metadata). An upgrade would bring any bug fixes and potential performance improvements since v0.12.18.
Best Practices (already applied β )
- Pre-compile with
gojq.Compile()atinit()β fail-fast validation at startup - Use
RunWithContext()β context cancellation/timeout propagated into jq execution - Type-assert
*gojq.HaltErrorspecifically β correct typed error handling - UTF-8 safe truncation β preview truncation walks back to nearest valid rune boundary
Improvement Opportunities
π Quick Wins
1. Upgrade to v0.12.19
The project uses v0.12.18; v0.12.19 is available. Standard bump via go get github.com/itchyny/gojq@latest + go mod tidy.
2. Rename the custom walk(f) def to avoid shadowing the built-in
The jq schema filter defines def walk(f) which shadows gojq's built-in walk/1. While it works and is well-documented in comments, using a distinct name like walk_schema avoids any potential future confusion:
def walk_schema:
if type == "object" then
reduce keys[] as $k ({}; . + {($k): (.[$k] | walk_schema)})
elif type == "array" then
if length == 0 then [] else [.[0] | walk_schema] end
else
type
end;
walk_schema3. Fix generateRandomID fallback collision risk
When crypto/rand.Read fails, the fallback is fmt.Sprintf("fallback-%d", os.Getpid()) β the same ID for every call within the same process. Concurrent tool calls would collide on payload file paths. A better fallback:
return fmt.Sprintf("fallback-%d-%d", os.Getpid(), time.Now().UnixNano())4. Tighten payload file permissions (security)
savePayload writes files with 0644 (world-readable). Since payloads may contain sensitive API responses, 0600 (owner read/write only) is more appropriate:
if err := os.WriteFile(filePath, payload, 0600); err != nil { // was 0644β¨ Feature Opportunities
5. gojq.WithFunction for native Go type helpers
gojq supports registering native Go functions callable from jq filters. For future extensibility (e.g., custom schema annotations, type overrides, field redaction), gojq.WithFunction could inject Go logic directly:
jqSchemaCode, err = gojq.Compile(query, gojq.WithFunction("go_type", 0, 0,
func(v interface{}, _ []interface{}) interface{} {
switch v.(type) {
case map[string]interface{}: return "object"
case []interface{}: return "array"
case string: return "string"
case float64: return "number"
case bool: return "boolean"
case nil: return "null"
default: return "unknown"
}
},
))6. gojq.WithVariables for configurable filter parameters
Schema filter options (max depth, excluded fields) could be passed as jq variables at compile time, enabling runtime customization without changing the filter string:
gojq.Compile(query, gojq.WithVariables([]string{"$excludeKeys"}))
// At run time:
code.RunWithContext(ctx, data, excludedKeysList)π Best Practice Alignment
7. Assert single-output contract in tests
The walk_schema filter always produces exactly one output value. Unit tests could verify this invariant by asserting iter.Next() returns false on the second call, documenting the contract and catching future filter changes that accidentally produce multiple outputs.
Recommendations
| Priority | Item | Effort |
|---|---|---|
| π΄ High | Fix generateRandomID fallback (collision risk on concurrent calls) |
Trivial |
| π΄ High | Fix payload file permissions: 0644 β 0600 |
Trivial |
| π‘ Medium | Upgrade gojq to v0.12.19 | Low |
| π‘ Medium | Rename def walk(f) to def walk_schema |
Low |
| π’ Low | Explore gojq.WithFunction for future extensibility |
Medium |
| π’ Low | Add single-output contract assertion in tests | Low |
Next Steps
- Fix
generateRandomIDfallback: addtime.Now().UnixNano()to avoid collisions - Change payload file write permission from
0644to0600 - Bump
github.com/itchyny/gojqtov0.12.19and rungo mod tidy - Rename
def walk(f)βdef walk_schemainjqSchemaFilterconstant
Generated by Go Fan πΉ
Module analysis saved to session artifacts: specs/mods/gojq.md
Note
π Integrity filter blocked 8 items
The following items were blocked because they don't meet the GitHub integrity level.
- https://github.com/BurntSushi/toml/releases/tag/v1.6.0
get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved". - https://github.com/wazero/wazero/releases/tag/v1.11.0
get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved". - https://github.com/stretchr/testify/releases/tag/v1.11.1
get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved". - golang/term@9d2dc07
list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved". - https://github.com/itchyny/gojq/releases/tag/v0.12.19
get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved". - https://github.com/spf13/cobra/releases/tag/v1.10.2
get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved". - https://github.com/santhosh-tekuri/jsonschema/releases/tag/v6.0.2
get_latest_release: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved". - get_file_contents
get_file_contents: has lower integrity than agent requires. The agent cannot read data with integrity below "unapproved".
To allow these resources, lower min-integrity in your GitHub frontmatter:
tools:
github:
min-integrity: approved # merged | approved | unapproved | none
- expires on Apr 10, 2026, 7:40 AM UTC