google / google/jsonschema-go

feat: allow custom regexp engine via RegexpCompiler option

Open
#72 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
478
Forks
37
PR merge metrics
No merged PRs in 30d

Description

**Is your feature request related to a problem? Please describe.**

The `doc.go` already acknowledges that Go's `regexp` package differs from ECMA 262 (no back-references, no lookahead/lookbehind). This is documented under "Deviations from the specification" with a link to the [regexp2 comparison table](https://github.com/dlclark/regexp2?tab=readme-ov-file#compare-regexp-and-regexp2).

Currently, there is no way to plug in an alternative regexp engine. Users working with schemas that use PCRE-specific features (e.g., `(?=...)` lookahead in `pattern` or `patternProperties`) cannot validate them correctly.

**Describe the solution you'd like**

Add a `RegexpCompiler` option to `ResolveOptions` that allows users to provide a custom regexp compiler. The default behavior remains unchanged (Go's `regexp.Compile`).

The proposed API:

```go
// A Regexp is a compiled regular expression.
type Regexp interface {
MatchString(s string) bool
}

// A RegexpCompiler compiles a regular expression pattern string into a Regexp.
type RegexpCompiler func(pattern string) (Regexp, error)

type ResolveOptions struct {
// ... existing fields ...

// RegexpCompiler compiles regular expression patterns used in "pattern" and
// "patternProperties" keywords. If nil, Go's regexp.Compile is used.
RegexpCompiler RegexpCompiler
}
```

Usage with `regexp2` (note: `regexp2.MatchString` returns `(bool, error)`, so an adapter is needed):

```go
import "github.com/dlclark/regexp2"

type regexp2Adapter struct {
re *regexp2.Regexp
}

func (r regexp2Adapter) MatchString(s string) bool {
ok, err := r.re.MatchString(s)
return err == nil && ok
}

compiler := func(pattern string) (jsonschema.Regexp, error) {
re, err := regexp2.Compile(pattern, regexp2.ECMAScript)
if err != nil {
return nil, err
}
return regexp2Adapter{re: re}, nil
}

resolved, err := schema.Resolve(&jsonschema.ResolveOptions{
RegexpCompiler: compiler,
})
```

**Implementation details**

- Minimal interface: `Regexp` requires only `MatchString(string) bool`, matching the existing validation path and avoiding changes to runtime validation semantics
- Internal `resolvedInfo` stores `Regexp` interface instead of `*regexp.Regexp`
- `validate.go` should require little or no change, since validation already only needs `MatchString` semantics
- `doc.go` "Deviations" section updated to mention the escape hatch
- Full test coverage: custom compiler for `pattern`, `patternProperties`, and error propagation
- Fully backwards-compatible — `nil` `RegexpCompiler` defaults to `regexp.Compile`

**PR:** https://github.com/google/jsonschema-go/pull/73

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.