Summary
printJSON (line ~48) and printJSONObject (line ~70) in cmd/jsonout.go contain character-for-character identical field-filter bodies:
// both functions repeat this block:
filtered := map[string]interface{}{}
for k, v := range row {
if requested[k] {
filtered[k] = v
}
}
Impact
Any change to filter semantics (e.g. case-insensitive keys, nested field support, allow-list ordering) must be applied twice. The duplication has already diverged once in the diff that introduced printJSONObject — it is a copy of printJSON's inner loop.
Fix
Extract a shared helper:
func filterFields(row map[string]interface{}, requested map[string]bool) map[string]interface{} {
if len(requested) == 0 {
return row
}
filtered := map[string]interface{}{}
for k, v := range row {
if requested[k] {
filtered[k] = v
}
}
return filtered
}
Callers become:
printJSON: for i, row := range rows { rows[i] = filterFields(row, requested) }
printJSONObject: row = filterFields(row, requested)
Zero behavioral change; single point of truth for filter logic.
Affected file
cmd/jsonout.go lines ~48–57, ~70–78
🤖 Generated with Claude Code
Summary
printJSON(line ~48) andprintJSONObject(line ~70) incmd/jsonout.gocontain character-for-character identical field-filter bodies:Impact
Any change to filter semantics (e.g. case-insensitive keys, nested field support, allow-list ordering) must be applied twice. The duplication has already diverged once in the diff that introduced
printJSONObject— it is a copy ofprintJSON's inner loop.Fix
Extract a shared helper:
Callers become:
printJSON:for i, row := range rows { rows[i] = filterFields(row, requested) }printJSONObject:row = filterFields(row, requested)Zero behavioral change; single point of truth for filter logic.
Affected file
cmd/jsonout.golines ~48–57, ~70–78🤖 Generated with Claude Code