πΉ Go Fan Report: santhosh-tekuri/jsonschema
Today's pick: github.com/santhosh-tekuri/jsonschema/v5 β chosen because a v6 major release (v6.0.2) is available that could eliminate 200+ lines of workaround code the project already has a TODO to investigate.
Module Overview
A Go JSON Schema validator (Drafts 4, 6, 7, 2019-09, 2020-12). Used here to validate MCP Gateway configuration at startup with fail-fast error reporting.
Current Usage in gh-aw
- Files: 4 (2 production, 2 test) β all in
internal/config/
- Key APIs:
NewCompiler(), compiler.Draft = jsonschema.Draft7, compiler.AddResource(), compiler.Compile(), schema.Validate(), *jsonschema.ValidationError
- Patterns: embedded schema compiled once via
sync.Once; custom schemas cached per-URL via sync.Map β both correct and idiomatic
Research Findings
v5.3.1 (in use) vs v6.0.2 (latest)
The library has a major version 6 at github.com/santhosh-tekuri/jsonschema/v6. The key difference: v6 fully supports Draft 2020-12, which uses ECMAScript 2019 regex β including negative lookahead assertions.
The Core Pain Point: fixSchemaBytes()
The embedded schema ($schema: draft-07) uses negative lookahead patterns like ^(?!stdio$|http$).*. Because v5/Draft7 doesn't handle them natively, validation_schema.go contains a ~200-line fixSchemaBytes() function that:
- Parses the schema JSON
- Removes negative-lookahead patterns, replacing them with
not: {enum: [...]} equivalents
- Patches missing fields (
registry, guard-policies, trustedBots, keepaliveInterval, headers)
- Re-serializes
There's already a TODO at line 97 of validation_schema.go flagging this:
// TODO: Investigate if JSON Schema v6 (library upgrade) or Draft 2019-09+/2020-12
// (newer spec) eliminate this workaround. The jsonschema/v6 Go library may handle
// these patterns natively, potentially allowing removal of this function entirely.
Improvement Opportunities
π Quick Wins
1. Reduce fragile message-string fallbacks in formatErrorContext
formatErrorContext() dispatches on the KeywordLocation-derived keyword (good, robust) but then falls back to strings.Contains(ve.Message, "additionalProperties") etc. These string-match fallbacks depend on the library's exact wording and can silently break across versions. Since KeywordLocation is already reliably populated, the fallback path should be minimized or removed.
2. Eliminate double JSON round-trip in validateServerAgainstSchema
The server config is json.Marshal-ed and immediately json.Unmarshal-ed to map[string]interface{} just to merge AdditionalProperties. A custom MarshalJSON or a direct struct-to-map builder would be cleaner and avoid the unnecessary allocation.
β¨ Feature Opportunities
1. Migrate to jsonschema/v6 β eliminate fixSchemaBytes() entirely β highest value
Upgrading to github.com/santhosh-tekuri/jsonschema/v6 + updating the embedded schema to Draft 2019-09 or 2020-12 should allow the negative-lookahead patterns to work natively, making fixSchemaBytes() (~200 lines + significant test code in fetch_and_fix_schema_test.go) obsolete.
Caveat: v6 has breaking API changes β ValidationError field names differ, requiring updates to formatValidationErrorRecursive and formatErrorContext. Needs a spike.
2. Implement a Loader for custom schema fetching
v5 exposes a Loader interface that customizes how schemas are fetched by URL. The project's fetchAndFixSchema() manually handles HTTP with retry logic. Implementing a custom Loader would integrate the retry + fix logic transparently into the compiler's $ref resolution.
π Best Practice Alignment
sync.Once schema caching β already done correctly; cached *Schema is reused across all validations
KeywordLocation dispatch β already using the correct, version-stable approach; the message-string fallbacks undermine it
- Add TTL comment on
customSchemaCache β the sync.Map has no expiry by design (startup-only validation); a comment would prevent well-intentioned but unnecessary "fixes"
Module Summary
References
Recommendations
- [HIGH] Spike
jsonschema/v6 migration β the existing TODO is already pointing at this. Potential to delete ~200 lines of workaround + tests.
- [MEDIUM] Remove fragile
strings.Contains(msg, ...) fallbacks in formatErrorContext β rely on KeywordLocation exclusively.
- [LOW] Eliminate double JSON round-trip in
validateServerAgainstSchema.
- [LOW] Add comment to
customSchemaCache explaining no-TTL is intentional.
Next Steps
Generated by Go Fan πΉ Β· Run Β§28084729068
Generated by Go Fan Β· 802.7 AIC Β· β 34.5K Β· β·
πΉ Go Fan Report: santhosh-tekuri/jsonschema
Today's pick:
github.com/santhosh-tekuri/jsonschema/v5β chosen because a v6 major release (v6.0.2) is available that could eliminate 200+ lines of workaround code the project already has aTODOto investigate.Module Overview
A Go JSON Schema validator (Drafts 4, 6, 7, 2019-09, 2020-12). Used here to validate MCP Gateway configuration at startup with fail-fast error reporting.
Current Usage in gh-aw
internal/config/NewCompiler(),compiler.Draft = jsonschema.Draft7,compiler.AddResource(),compiler.Compile(),schema.Validate(),*jsonschema.ValidationErrorsync.Once; custom schemas cached per-URL viasync.Mapβ both correct and idiomaticResearch Findings
v5.3.1 (in use) vs v6.0.2 (latest)
The library has a major version 6 at
github.com/santhosh-tekuri/jsonschema/v6. The key difference: v6 fully supports Draft 2020-12, which uses ECMAScript 2019 regex β including negative lookahead assertions.The Core Pain Point:
fixSchemaBytes()The embedded schema (
$schema: draft-07) uses negative lookahead patterns like^(?!stdio$|http$).*. Because v5/Draft7 doesn't handle them natively,validation_schema.gocontains a ~200-linefixSchemaBytes()function that:not: {enum: [...]}equivalentsregistry,guard-policies,trustedBots,keepaliveInterval,headers)There's already a
TODOat line 97 ofvalidation_schema.goflagging this:Improvement Opportunities
π Quick Wins
1. Reduce fragile message-string fallbacks in
formatErrorContextformatErrorContext()dispatches on theKeywordLocation-derived keyword (good, robust) but then falls back tostrings.Contains(ve.Message, "additionalProperties")etc. These string-match fallbacks depend on the library's exact wording and can silently break across versions. SinceKeywordLocationis already reliably populated, the fallback path should be minimized or removed.2. Eliminate double JSON round-trip in
validateServerAgainstSchemaThe server config is
json.Marshal-ed and immediatelyjson.Unmarshal-ed tomap[string]interface{}just to mergeAdditionalProperties. A customMarshalJSONor a direct struct-to-map builder would be cleaner and avoid the unnecessary allocation.β¨ Feature Opportunities
1. Migrate to
jsonschema/v6β eliminatefixSchemaBytes()entirely β highest valueUpgrading to
github.com/santhosh-tekuri/jsonschema/v6+ updating the embedded schema to Draft 2019-09 or 2020-12 should allow the negative-lookahead patterns to work natively, makingfixSchemaBytes()(~200 lines + significant test code infetch_and_fix_schema_test.go) obsolete.Caveat: v6 has breaking API changes β
ValidationErrorfield names differ, requiring updates toformatValidationErrorRecursiveandformatErrorContext. Needs a spike.2. Implement a
Loaderfor custom schema fetchingv5 exposes a
Loaderinterface that customizes how schemas are fetched by URL. The project'sfetchAndFixSchema()manually handles HTTP with retry logic. Implementing a customLoaderwould integrate the retry + fix logic transparently into the compiler's$refresolution.π Best Practice Alignment
sync.Onceschema caching β already done correctly; cached*Schemais reused across all validationsKeywordLocationdispatch β already using the correct, version-stable approach; the message-string fallbacks undermine itcustomSchemaCacheβ thesync.Maphas no expiry by design (startup-only validation); a comment would prevent well-intentioned but unnecessary "fixes"Module Summary
github.com/santhosh-tekuri/jsonschema/v5v5.3.1v6.0.2(major version ahead)References
Recommendations
jsonschema/v6migration β the existingTODOis already pointing at this. Potential to delete ~200 lines of workaround + tests.strings.Contains(msg, ...)fallbacks informatErrorContextβ rely onKeywordLocationexclusively.validateServerAgainstSchema.customSchemaCacheexplaining no-TTL is intentional.Next Steps
jsonschema/v6, update schema$schemato Draft 2020-12, verifyfixSchemaBytescan be removedValidationErrorfield compatibility with existing error-formatting codefixSchemaBytes+ all associated testsGenerated by Go Fan πΉ Β· Run Β§28084729068