fix(json): make JSON Schema enum compile again - #572
Merged
Conversation
wolfy-j
force-pushed
the
fix/json-schema-enum-compile
branch
from
August 15, 2026 22:35
e855c4f to
4153b40
Compare
skhaz
approved these changes
Aug 17, 2026
wolfy-j
force-pushed
the
fix/json-schema-enum-compile
branch
from
August 19, 2026 14:28
4153b40 to
e007a01
Compare
Any JSON Schema carrying an `enum` currently fails to compile, before any
data is examined:
json: cannot unmarshal into Go *interface {} within
"/properties/state/enum/0": unsupported operation
Neither this repo nor github.com/kaptinlin/jsonschema is at fault.
github.com/go-json-experiment/json ships two implementations behind build tags
which disagree on how a custom unmarshaler signals "skip me":
!goexperiment.jsonv2 arshal_funcs.go errors.ErrUnsupported
goexperiment.jsonv2 && go1.25 alias.go stdlib SkipFunc, not re-exported
kaptinlin/jsonschema returns errors.ErrUnsupported from the *any unmarshaler it
installs for JSON number handling (compiler.go:21-24), exactly as the standalone
package documents. Under the alias, encoding/json/v2 treats that as fatal, and
json.SkipFunc is not reachable through the alias at all -- substituting it in a
local copy of the dependency fails to compile with "undefined: json.SkipFunc".
So under the experiment a dependency cannot signal skip by any means. An enum
array is the common place a non-number value reaches that code path, which is
why enum is the keyword that surfaces it. The alias is not a faithful drop-in
for the package it replaces, and that is not fixable from here, so the
experiment is disabled until it is. Re-enabling is a one-line revert.
Upgrading the dependency does not help: v0.9.8 fails identically.
Disabling the experiment activates decode_v1.go, which was not behaviourally
equivalent to decode_v2.go: it sized the object table from the decoded map, so
an empty JSON object allocated no string dictionary and re-encoded as []. It now
allocates the dictionary the way decodeObject does on the v2 path.
Both behaviours are pinned by tests that fail before this change and pass after.
Cost: decode_v2.go imports stdlib encoding/json/jsontext and so requires the
experiment, meaning the fast decoder and working schema validation cannot
currently coexist. Measured on this branch at 200x --
Simple 964ns -> 1360ns
Complex 2934ns -> 5907ns
LargeArray 33.9us -> 66.1us
LargeDataset 1.29ms -> 2.78ms
roughly 1.4-2.2x on decode. A third option keeps both, at the cost of a
maintained fork: replace go-json-experiment/json with one whose alias.go build
tag is dropped, so dependencies keep the standalone semantics while this repo
keeps the experiment for its own jsontext use.
go test ./runtime/... ./internal/... ./api/... -short passes.
wolfy-j
force-pushed
the
fix/json-schema-enum-compile
branch
from
August 19, 2026 14:35
e007a01 to
8f0851c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
JSON Schemas containing
enumfail during compilation in official builds:kaptinlin/jsonschemauses the standalonego-json-experiment/jsonunmarshaler fallback contract. WithGOEXPERIMENT=jsonv2, that module becomes an alias over the standard-library implementation, which uses a different, unexported skip sentinel. The dependency can no longer request default unmarshaling.Resolution
GOEXPERIMENT=nojsonv2so schema compilation uses the supported standalone implementation.github.com/go-json-experiment/json/jsontextdirectly.int64, larger JSON integers, floats, and unrepresentable numbers explicitly.Performance
The fix does not retain the slower intermediate
map[string]anydecoder. Representative results on an AMD Ryzen 9 7950X3D,-benchtime=500ms, five runs:These allocation counts match the previous experimental fast decoder. Cached enum validation is approximately 2.2–2.9 µs at 2,443 bytes and 32 allocations per operation. Allocation profiling attributes the remaining validation cost primarily to
kaptinlin/jsonschemaevaluation-result construction.Verification
make lintmake test-runtimego mod tidy -diff