Skip to content

Instantly share code, notes, and snippets.

@dims
Last active February 10, 2026 14:18
Show Gist options
  • Select an option

  • Save dims/31e0b95374981a8adf0d62b4c328d048 to your computer and use it in GitHub Desktop.

Select an option

Save dims/31e0b95374981a8adf0d62b4c328d048 to your computer and use it in GitHub Desktop.
Review: Update go-openapi dependencies (jsonpointer, jsonreference, swag) - k8s PR #136819

Review: Update go-openapi dependencies (jsonpointer, jsonreference, swag)

Commit: 4e555defc1b555afa9b24ab5fa1c74bb79b04be3 Author: Davanum Srinivas [email protected] Date: Sat Feb 7 08:09:42 2026 -0500 Repo: k8s.io/kubernetes PR: kubernetes/kubernetes#136819 Branch: update-go-openapi-deps -> master


1) Summary

This commit bumps three go-openapi dependencies to their latest versions. The most significant change is the restructuring of go-openapi/swag from a single package into a multi-module monorepo with 11 submodules, which eliminates mailru/easyjson and josharian/intern as transitive dependencies. No Kubernetes .go source files outside vendor/ are modified — the commit touches only go.mod, staging go.mod/go.sum, vendor/, and hack/unwanted-dependencies.json.

Net impact: 197 files changed (+13,329 / -6,267). Two dependencies removed (easyjson, intern), 11 new swag/* submodules added (all // indirect), 3 libraries version-bumped. Seven entries removed from hack/unwanted-dependencies.json.


2) Dependency Changes

Version bumps

Package Old New Min Go
go-openapi/jsonpointer v0.21.0 v0.22.4 1.24.0 (was 1.20)
go-openapi/jsonreference v0.20.2 v0.21.4 1.24.0 (was 1.13)
go-openapi/swag v0.23.0 v0.25.4 1.24.0 (was 1.20)

The repo's go 1.25.0 in go.mod exceeds the new 1.24.0 requirement, so no toolchain issue.

Dependencies removed

Package Version Removed because
mailru/easyjson v0.7.7 swag now uses a stdlib JSON adapter; easyjson is opt-in
josharian/intern v1.0.0 Was a transitive dep of easyjson

Dependencies added (new swag submodules)

All at v0.25.4, all // indirect:

Module Purpose
swag/cmdutils CLI utilities
swag/conv Type conversion (generic, replaces old convert.go)
swag/fileutils File/path utilities
swag/jsonname JSON name provider (struct tag -> JSON name resolution)
swag/jsonutils JSON operations: concat, marshal, ordered maps
swag/loading File/HTTP spec loading
swag/mangling Name mangling (ToGoName, ToFileName, etc.)
swag/netutils Network utilities
swag/stringutils String/collection format utilities
swag/typeutils Go type utilities
swag/yamlutils YAML utilities

Structural change

swag v0.24.0+ was refactored into a Go monorepo: each subpackage is an independent Go module with its own go.mod. The root swag module re-exports everything via *_iface.go wrapper files for backward compatibility. The dependency chain changed:

Before: jsonreference -> jsonpointer -> swag -> easyjson -> intern
After:  jsonreference -> jsonpointer -> swag/jsonname (lightweight)

Policy file changes

hack/unwanted-dependencies.json — 7 entries removed:

  • go-openapi/jsonpointer and go-openapi/swag removed from davecgh/go-spew unwanted list
  • go-openapi/jsonpointer and go-openapi/swag removed from mailru/easyjson unwanted list
  • go-openapi/jsonpointer and go-openapi/swag removed from gopkg.in/yaml.v3 unwanted list
  • mailru/easyjson removed from the top-level unwanted dependency list

3) Upstream Signal (Changelogs + Commits)

go-openapi/jsonpointer v0.21.0 -> v0.22.4

Compare: https://github.com/go-openapi/jsonpointer/compare/v0.21.0...v0.22.4 (55 commits)

Version Date Key changes
v0.21.2 2025-08 Bug fix: prevent panic on nil intermediate values during Set operations. Returns descriptive errors instead of reflect: call of reflect.Value.Type on zero Value.
v0.22.0 2025-08-30 easyjson removal: replaced go-openapi/swag import with go-openapi/swag/jsonname.
v0.22.1 2025-09 Minor perf optimization for Escape/Unescape.
v0.22.2 2025-11 Added govulscan security scanner, fuzz testing, NOTICE file.
v0.22.3 2025-11 Documentation, contributor tracking, edge-case tests.
v0.22.4 2025-12 CI-only: aligned with shared workflows. No functional change.

Security: No CVEs. Added govulscan scanner to CI (v0.22.2). Breaking: None. All exported signatures preserved.

go-openapi/jsonreference v0.20.2 -> v0.21.4

Compare: https://github.com/go-openapi/jsonreference/compare/v0.20.2...v0.21.4 (49 commits)

Version Date Key changes
v0.21.0 2024-03 Bumped minimum Go to 1.20 across go-openapi.
v0.21.1 2025-08 easyjson removal (transitive, via updated jsonpointer).
v0.21.3 2025-11 Switched test framework from stretchr/testify to go-openapi/testify. Updated license headers.
v0.21.4 2025-12 CI alignment with shared workflows. Updated jsonpointer to v0.22.4.

Security: None. Breaking: None. One new export: ErrChildURL sentinel error.

go-openapi/swag v0.23.0 -> v0.25.4

Tags: https://github.com/go-openapi/swag/tags (no GitHub Releases; tags only). 63 commits.

Version Date Key changes
v0.24.0 2025-08-30 Monorepo restructuring: split into 11 subpackages, then into independent Go modules. New features: LoadingOptions for configurable HTTP/file loading; pluralized initialism support in name mangling; generic type conversions in conv. Retracted due to mono-repo go.mod release issue.
v0.24.1 2025-08-30 Fixed go.mod for monorepo release.
v0.25.0 2025-09-23 easyjson removal: JSON serialization defaults to stdlib. Introduced adapter pattern (jsonutils/adapters/) -- easyjson available as opt-in via Register(). Also removed direct gopkg.in/yaml.v3 dependency.
v0.25.1 2025-09-26 Bug fix: data race in stdlib JSON lexer.
v0.25.2 2025-10 Removed most remaining external deps. Added SECURITY.md. Pinned GitHub Actions to SHA.
v0.25.3 2025-11 Bug fix: name mangler panics on trailing pluralized initialisms.
v0.25.4 2025-11 Bug fix: overlapping pluralized initialisms trigger panic.

Security: Added security policy (v0.25.2). SHA-pinned GitHub Actions (v0.25.2). No CVEs. Breaking: v0.24.0 retracted (fixed in v0.24.1). Root package backward-compatible via *_iface.go.

Coordinated easyjson removal timeline

Library Version Date Mechanism
swag v0.25.0 2025-09-23 Primary: introduced stdlib adapter, made easyjson opt-in
jsonpointer v0.22.0 2025-08-30 Switched from swag to swag/jsonname (lightweight submodule)
jsonreference v0.21.1 2025-08-30 Transitive: updated jsonpointer dependency

4) API Surface & Backward Compatibility

swag root package

Full backward compatibility via deprecated wrapper files. Every previously exported function, type, and variable is preserved:

Wrapper file Delegates to Key symbols
conv_iface.go swag/conv ConvertBool, ConvertFloat64, Int64Value, StringSlice, ~480 lines
mangling_iface.go swag/mangling ToGoName, ToFileName, ToCommandName, GoNamePrefixFunc
jsonutils_iface.go swag/jsonutils ConcatJSON, WriteJSON, ReadJSON, JSONMapSlice, JSONMapItem
loading_iface.go swag/loading LoadFromFileOrHTTP, LoadStrategy, LoadHTTPTimeout
jsonname_iface.go swag/jsonname DefaultJSONNameProvider, NameProvider (type alias)
fileutils_iface.go swag/fileutils FindInSearchPath, FindInGoSearchPath
stringutils_iface.go swag/stringutils SplitByFormat, JoinByFormat
yamlutils_iface.go swag/yamlutils BytesToYAMLDoc, YAMLToJSON
netutils_iface.go swag/netutils SplitHostPort
typeutils_iface.go swag/typeutils IsZero
cmdutils_iface.go swag/cmdutils CommandLineOptionsGroup

Import path github.com/go-openapi/swag is unchanged.

jsonpointer

All exported signatures preserved (verified by diffing grep "^func" on old vs new pointer.go):

Symbol Signature Changed?
New(string) (Pointer, error) No
Pointer.Get(any) (any, reflect.Kind, error) No
Pointer.Set(any, any) (any, error) No
GetForToken(any, string) (any, reflect.Kind, error) No
SetForToken(any, string, any) (any, error) No
Pointer.DecodedTokens() []string No
Pointer.IsEmpty() bool No
Pointer.String() string No
Pointer.Offset(string) (int64, error) No
Escape(string) string No
Unescape(string) string No

New exports (additive, non-breaking): ErrPointer, ErrInvalidStart, ErrUnsupportedValueType sentinel errors.

jsonreference

All exported signatures preserved. New export: ErrChildURL (sentinel, replaces inline errors.New("child url is nil") in Ref.Inherits).


5) Behavioral Changes

5.1 jsonpointer: nil-panic fix in Set operations (v0.21.2)

Old: Set on a path with nil intermediate values panics with reflect: call of reflect.Value.Type on zero Value. New: Returns a descriptive error: "cannot set field X on nil value". Affected: Any code calling jsonpointer.Set where intermediate nodes may be nil. This is a bug fix -- the old behavior was a panic.

5.2 jsonpointer: error wrapping (v0.22.0+)

Old: Errors were plain strings (e.g., "nil value has not field %q"). New: Errors wrap ErrPointer sentinel via %w, use correct grammar ("has no field" not "has not field"). Affected: Code doing err.Error() == "..." string matching on jsonpointer errors. New pattern: errors.Is(err, jsonpointer.ErrPointer).

5.3 jsonpointer: stricter Set validation (v0.22.0+)

New: Set performs explicit CanSet and AssignableTo checks before mutation. Previously it could silently fail or panic on unaddressable/incompatible values. Now returns ErrUnsupportedValueType. Affected: Code relying on implicit type conversions during pointer-based mutation.

5.4 swag JSON backend: stdlib replaces easyjson (v0.25.0)

Old: swag used mailru/easyjson internally for JSON operations (lexer, writer, concat). New: swag/jsonutils uses a stdlib-based adapter by default. easyjson available as opt-in via swag/jsonutils/adapters/easyjson/json.Register(). Affected: Edge cases in JSON serialization (key ordering, whitespace, large number handling) may differ. A data race in the new stdlib lexer was fixed in v0.25.1.

5.5 swag name mangling: pluralized initialism panics (v0.25.3, v0.25.4)

Old (v0.24.0): New pluralized initialism support panicked on trailing/overlapping initialisms. New: Fixed. Both panic conditions resolved. Affected: Only code calling swag.ToGoName with inputs containing trailing pluralized initialisms (e.g., "someAPIs").

5.6 jsonreference: ErrChildURL sentinel (v0.21.4)

Old: Ref.Inherits() returned errors.New("child url is nil"). New: Returns package-level ErrChildURL var. Affected: Only code string-matching that exact error message.


6) Impact on This Repo

6.1 Direct imports (non-vendor, including staging/)

go-openapi/jsonpointer: Zero direct imports in non-vendor code.

go-openapi/jsonreference: Two files:

File Line Usage Affected?
staging/.../kubectl/pkg/explain/v2/funcs.go 207 jsonreference.New(refString) -- parses reference strings, checks HasFragmentOnly, calls GetURL().Fragment No. Parses references only, no pointer resolution into structs.
pkg/generated/openapi/openapi_test.go 60 jsonreference.Ref in cmp.Comparer -- compares via .String() No. String comparison only.

go-openapi/swag: Zero direct imports in non-vendor code.

6.2 Indirect usage via kube-openapi (vendored)

Multiple files in staging/src/k8s.io/apiextensions-apiserver/ use kube-openapi/pkg/validation/spec types (spec.Schema, spec.Ref, spec.SchemaOrArray, etc.):

  • pkg/apiserver/schema/kubeopenapi.go -- type conversions using spec.Schema
  • pkg/apiserver/validation/validation.go -- schema validation
  • pkg/controller/openapi/v2/conversion_test.go -- spec.NewRef(url), spec.Schema in tests
  • pkg/apiserver/validation/formats.go -- references "go-openapi default format name normalization" in comments

These all use spec.* types which internally depend on swag and jsonreference, but the k8s code operates at the spec abstraction level. The vendored kube-openapi code (vendor/k8s.io/kube-openapi/pkg/validation/spec/schema.go lines 574, 619) calls swag.DefaultJSONNameProvider.GetJSONNames() -- this still works through the deprecated type alias in jsonname_iface.go.

6.3 Code-generator jsonpointer usage

staging/.../code-generator/.../openapi.go:124 calls def.Ref.GetPointer() then IsEmpty() / String(). These are pointer metadata operations (checking emptiness, getting string form), not struct field resolution. Not affected.

6.4 Error string matching

Zero occurrences of jsonpointer error string matching in non-vendor code. Searched for: "Can't find the pointer", "JSON pointer must be empty", "not found" in context of jsonpointer errors.

6.5 easyjson/intern usage

Zero occurrences of easyjson or josharian/intern imports in non-vendor code.

6.6 Struct tag analysis

Types used with jsonpointer/jsonreference that have untagged exported fields:

Type Untagged fields Risk
jsonreference.Ref HasFullURL, HasURLPathOnly, HasFragmentOnly, HasFileScheme, HasFullFilePath None -- no code resolves a JSON pointer into a Ref struct
spec.VendorExtensible Extensions (embedded in spec.Schema) None -- handled by custom UnmarshalJSON, not jsonpointer

6.7 NameProvider / custom interfaces

No non-vendor Kubernetes code creates custom NameProvider instances, implements JSONPointable, or implements JSONSetable.


7) Risk Assessment

Risk Description Likelihood Severity Affected code
Compile-time breakage All exported API signatures preserved; deprecated wrappers in place None N/A N/A
Runtime: nil-panic fix Set on nil intermediates returns error instead of panicking Positive N/A (fix) No k8s code calls Set with nil intermediates
Runtime: error wrapping jsonpointer errors now wrap ErrPointer; text changed Low Low No k8s code string-matches jsonpointer errors
Runtime: stricter Set Set validates CanSet/AssignableTo before mutation Low Low No k8s code calls jsonpointer.Set directly
Performance: stdlib JSON JSON ops use stdlib adapter instead of easyjson Low Low Vendored kube-openapi JSON operations only
Downstream: API Deprecated wrappers still work; import paths unchanged Low Low Out-of-tree code importing swag
Downstream: easyjson Code relying on automatic easyjson usage loses fast path Medium Low Out-of-tree code that depended on easyjson perf
Downstream: mangling panics Fixed panics in pluralized initialisms Positive N/A (fix) Out-of-tree code using ToGoName
Toolchain: Go 1.24.0 min All three libraries require go 1.24.0 None N/A Repo uses go 1.25.0

8) Verdict

Safe to merge.

The commit achieves a meaningful reduction in dependency surface (removes easyjson and intern) while maintaining full backward compatibility. All three libraries preserve their exported API signatures, with deprecated wrappers in swag forwarding to the new submodules. The behavioral changes (nil-panic fix, error wrapping, stdlib JSON backend) are either bug fixes or don't affect any Kubernetes code path -- verified by grepping all non-vendor source including staging. The only theoretical risk is subtle JSON serialization differences from the stdlib-vs-easyjson backend swap, but this is confined to vendored kube-openapi internals and is well-tested upstream (data race fixed in v0.25.1, panic fixes in v0.25.3/v0.25.4). No Kubernetes .go files outside vendor/ are modified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment