Skip to content

refactor: jq middleware improvements from gojq module review#3026

Merged
lpcox merged 2 commits intomainfrom
refactor/jq-middleware-2985
Apr 1, 2026
Merged

refactor: jq middleware improvements from gojq module review#3026
lpcox merged 2 commits intomainfrom
refactor/jq-middleware-2985

Conversation

@lpcox
Copy link
Copy Markdown
Collaborator

@lpcox lpcox commented Apr 1, 2026

Summary

Implements the quick-win improvements identified in the gojq module review (#2985).

Changes

1. Remove duplicate test helper

Deleted integrationPayloadMetadataToMap from jqschema_integration_test.go — it was byte-for-byte identical to payloadMetadataToMap in jqschema_test.go. Both files are in package middleware, so the shared helper is directly usable.

2. Document custom walk vs built-in

Added a comment block explaining why jqSchemaFilter defines its own walk function instead of using gojq's built-in walk(f):

  • Built-in walk(f) applies f post-recursion but preserves structure
  • Our custom walk replaces leaf values with type names AND collapses arrays to first element
  • These behaviors are incompatible with standard walk(f) semantics

3. Document single-result iterator contract

Added comment explaining why iter.Next() is called only once — the walk(.) filter produces exactly one output value.

4. UTF-8 safety comment on preview truncation

Documented why byte-level slicing at PayloadPreviewSize is safe: json.Marshal escapes non-ASCII runes as \uXXXX, so every byte boundary is a valid UTF-8 boundary.

5. Skip redundant JSON unmarshal

Added a type-switch in WrapToolHandler that skips the json.Unmarshal step when data is already map[string]interface{} or []interface{}. This avoids a needless marshal→unmarshal round-trip on hot paths.

Closes #2985

- Remove duplicate integrationPayloadMetadataToMap test helper; use the
  shared payloadMetadataToMap across both test files
- Document why a custom walk function is used instead of gojq's built-in
  walk(f) (structural array collapse + leaf type replacement)
- Document single-result iterator contract (walk(.) produces exactly one
  output)
- Add UTF-8 safety comment on preview truncation (json.Marshal output is
  ASCII-clean, so byte-level slicing is safe)
- Skip redundant JSON unmarshal in WrapToolHandler when data is already a
  native Go type (map[string]interface{} or []interface{})

Closes #2985

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 1, 2026 22:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR applies “quick-win” improvements from the gojq module review (#2985) to the jq schema middleware, focusing on documentation clarity and avoiding unnecessary JSON processing on hot paths.

Changes:

  • Removed a duplicate test helper in jqschema_integration_test.go in favor of the shared helper in jqschema_test.go.
  • Added explanatory comments around the custom jq walk implementation and the single-result iterator contract.
  • Added a type-switch optimization in WrapToolHandler to avoid redundant marshal → unmarshal when the payload is already map[string]interface{} / []interface{}.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
internal/middleware/jqschema.go Adds documentation clarifications and an optimization to skip redundant unmarshaling before running gojq.
internal/middleware/jqschema_integration_test.go Removes duplicated helper and reuses the existing shared test helper.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +379 to +382
//
// Byte-level slicing is safe here because json.Marshal produces ASCII-clean output:
// non-ASCII runes are escaped as \uXXXX sequences, so every byte boundary is a
// valid UTF-8 boundary.
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UTF-8 safety rationale here is incorrect: encoding/json.Marshal emits UTF-8 for non-ASCII runes (it does not generally escape them as \uXXXX). Byte-slicing payloadJSON at an arbitrary boundary can split a multi-byte UTF-8 sequence, so the preview string may be invalid UTF-8. Either adjust the truncation to a valid rune boundary (or validate/repair), or update the comment to accurately describe the behavior and its implications for downstream JSON encoding/logging.

Copilot uses AI. Check for mistakes.
json.Marshal emits raw UTF-8 (not \uXXXX escapes) for non-ASCII runes,
so byte-level slicing can split multi-byte sequences. Adjust the cut
point backward to the nearest valid rune boundary using utf8.RuneStart.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[go-fan] Go Module Review: itchyny/gojq

2 participants