From 8ce4c47614deadaf2c198f9c03e5dfec2520854c Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 15 Jun 2026 09:56:09 -0400 Subject: [PATCH 1/3] Fix validator to use libopenapi v0.38.0 lazy GetSpecJSON getters Signed-off-by: Reinhard Tartler --- go.mod | 8 ++++---- go.sum | 6 ++++++ schema_validation/validate_document.go | 14 +++++++------- schema_validation/validate_document_test.go | 9 +++++++++ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 87c3653..72d0b71 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/pb33f/libopenapi-validator -go 1.25.0 +go 1.25.7 require ( github.com/basgys/goxml2json v1.1.1-0.20231018121955-e66ee54ceaad @@ -8,10 +8,10 @@ require ( github.com/go-openapi/jsonpointer v0.23.1 github.com/goccy/go-yaml v1.19.2 github.com/pb33f/jsonpath v0.8.2 - github.com/pb33f/libopenapi v0.37.2 + github.com/pb33f/libopenapi v0.38.0 github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 github.com/stretchr/testify v1.11.1 - go.yaml.in/yaml/v4 v4.0.0-rc.4 + go.yaml.in/yaml/v4 v4.0.0-rc.5 golang.org/x/text v0.37.0 ) @@ -24,7 +24,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect golang.org/x/net v0.50.0 // indirect - golang.org/x/sync v0.20.0 // indirect + golang.org/x/sync v0.21.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index d8a0ec2..f76ea1b 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/pb33f/jsonpath v0.8.2 h1:Ou4C7zjYClBm97dfZjDCjdZGusJoynv/vrtiEKNfj2Y= github.com/pb33f/jsonpath v0.8.2/go.mod h1:zBV5LJW4OQOPatmQE2QdKpGQJvhDTlE5IEj6ASaRNTo= github.com/pb33f/libopenapi v0.37.2 h1:4Kb4w/h2BVKb099oYIZqeDxEBhUioWA+z6WJhBOk2r8= github.com/pb33f/libopenapi v0.37.2/go.mod h1:MsDdUlQ1CdrIDO5v26JfgBxQs7kcaOUEpMP3EqU6bI4= +github.com/pb33f/libopenapi v0.38.0 h1:OG+AMr2dMeB0BZdmm+j6iFy3Uxyl+W0HZpdD72zcyGs= +github.com/pb33f/libopenapi v0.38.0/go.mod h1:HrXjcGH/igq+/Af5l5/hmDD+yQRBRiTHgl0FmLdCZjg= github.com/pb33f/ordered-map/v2 v2.3.1 h1:5319HDO0aw4DA4gzi+zv4FXU9UlSs3xGZ40wcP1nBjY= github.com/pb33f/ordered-map/v2 v2.3.1/go.mod h1:qxFQgd0PkVUtOMCkTapqotNgzRhMPL7VvaHKbd1HnmQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -45,6 +47,8 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U= go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= +go.yaml.in/yaml/v4 v4.0.0-rc.5 h1:JVliQq9EGOYaTgMi+k8BhUJyqcGk4ZqeuiN1Cirba9c= +go.yaml.in/yaml/v4 v4.0.0-rc.5/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= @@ -63,6 +67,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/schema_validation/validate_document.go b/schema_validation/validate_document.go index d539db4..e1ef930 100644 --- a/schema_validation/validate_document.go +++ b/schema_validation/validate_document.go @@ -236,7 +236,7 @@ func ValidateOpenAPIDocumentWithPrecompiled(doc libopenapi.Document, compiledSch var validationErrors []*liberrors.ValidationError // Check if both JSON representations are nil before proceeding - if info.SpecJSON == nil && info.SpecJSONBytes == nil { + if info.GetSpecJSON() == nil && info.GetSpecJSONBytes() == nil { validationErrors = append(validationErrors, &liberrors.ValidationError{ ValidationType: helpers.Schema, ValidationSubType: "document", @@ -279,13 +279,13 @@ func ValidateOpenAPIDocumentWithPrecompiled(doc libopenapi.Document, compiledSch // Build the normalized document value for validation. // Prefer SpecJSONBytes (single unmarshal) over SpecJSON (marshal+unmarshal round-trip). var normalized any - if info.SpecJSONBytes != nil && len(*info.SpecJSONBytes) > 0 { + if info.GetSpecJSONBytes() != nil && len(*info.GetSpecJSONBytes()) > 0 { var err error - normalized, err = jsonschema.UnmarshalJSON(bytes.NewReader(*info.SpecJSONBytes)) + normalized, err = jsonschema.UnmarshalJSON(bytes.NewReader(*info.GetSpecJSONBytes())) if err != nil { // Fall back to normalizeJSON if UnmarshalJSON fails - if info.SpecJSON != nil { - normalized, err = normalizeJSON(*info.SpecJSON) + if info.GetSpecJSON() != nil { + normalized, err = normalizeJSON(*info.GetSpecJSON()) if err != nil { return false, []*liberrors.ValidationError{buildDocumentDecodeError( fmt.Sprintf("The OpenAPI document cannot be converted to JSON: %s", err.Error()), @@ -299,9 +299,9 @@ func ValidateOpenAPIDocumentWithPrecompiled(doc libopenapi.Document, compiledSch )} } } - } else if info.SpecJSON != nil { + } else if info.GetSpecJSON() != nil { var err error - normalized, err = normalizeJSON(*info.SpecJSON) + normalized, err = normalizeJSON(*info.GetSpecJSON()) if err != nil { return false, []*liberrors.ValidationError{buildDocumentDecodeError( fmt.Sprintf("The OpenAPI document cannot be converted to JSON: %s", err.Error()), diff --git a/schema_validation/validate_document_test.go b/schema_validation/validate_document_test.go index 6f8e2f1..434567a 100644 --- a/schema_validation/validate_document_test.go +++ b/schema_validation/validate_document_test.go @@ -210,6 +210,7 @@ paths: {}` }, } info := doc.GetSpecInfo() + info.GetSpecJSON() info.SpecJSON = &badSpecJSON info.SpecJSONBytes = nil @@ -240,6 +241,7 @@ paths: {}` } corrupt := []byte(`{not valid json!!!}`) info := doc.GetSpecInfo() + info.GetSpecJSON() info.SpecJSON = &badSpecJSON info.SpecJSONBytes = &corrupt @@ -431,6 +433,7 @@ info: // Simulate the nil SpecJSON scenario by setting both to nil info := doc.GetSpecInfo() + info.GetSpecJSON() info.SpecJSON = nil info.SpecJSONBytes = nil @@ -460,6 +463,7 @@ func TestValidateDocument_WithPrecompiledSchema(t *testing.T) { doc, _ := libopenapi.NewDocument(petstore) info := doc.GetSpecInfo() + info.GetSpecJSON() // Pre-compile the schema options := config.NewValidationOptions() @@ -482,6 +486,7 @@ func TestValidateDocument_WithPrecompiledSchema_Invalid(t *testing.T) { doc, _ := libopenapi.NewDocument(petstore) info := doc.GetSpecInfo() + info.GetSpecJSON() // Pre-compile the schema options := config.NewValidationOptions() @@ -506,6 +511,7 @@ func TestValidateDocument_SpecJSONBytesPath(t *testing.T) { doc, _ := libopenapi.NewDocument(petstore) info := doc.GetSpecInfo() + info.GetSpecJSON() // Nil out SpecJSON but leave SpecJSONBytes intact — forces the SpecJSONBytes path assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") @@ -521,6 +527,7 @@ func TestValidateDocument_SpecJSONBytesCorrupt_NilSpecJSON(t *testing.T) { doc, _ := libopenapi.NewDocument(petstore) info := doc.GetSpecInfo() + info.GetSpecJSON() // Put corrupt bytes in SpecJSONBytes so UnmarshalJSON fails, // and nil out SpecJSON so the fallback normalizeJSON path is skipped. @@ -542,6 +549,7 @@ func TestValidateDocument_SpecJSONBytesCorrupt_FallbackToSpecJSON(t *testing.T) doc, _ := libopenapi.NewDocument(petstore) info := doc.GetSpecInfo() + info.GetSpecJSON() // Put corrupt bytes in SpecJSONBytes so UnmarshalJSON fails, // but leave SpecJSON intact so the fallback to normalizeJSON executes. @@ -559,6 +567,7 @@ func TestValidateDocument_SpecJSONBytesPath_Invalid(t *testing.T) { doc, _ := libopenapi.NewDocument(petstore) info := doc.GetSpecInfo() + info.GetSpecJSON() // Nil out SpecJSON but leave SpecJSONBytes intact assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") From 1ccb2909a067f0311f78daecf1207fe20814f2c2 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 15 Jun 2026 14:15:28 -0400 Subject: [PATCH 2/3] test: ignore staticcheck SA1019 deprecation warnings on lazy getters fallback paths --- schema_validation/validate_document_test.go | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/schema_validation/validate_document_test.go b/schema_validation/validate_document_test.go index 434567a..6e144dc 100644 --- a/schema_validation/validate_document_test.go +++ b/schema_validation/validate_document_test.go @@ -211,8 +211,8 @@ paths: {}` } info := doc.GetSpecInfo() info.GetSpecJSON() - info.SpecJSON = &badSpecJSON - info.SpecJSONBytes = nil + info.SpecJSON = &badSpecJSON //nolint:staticcheck + info.SpecJSONBytes = nil //nolint:staticcheck valid, errors := ValidateOpenAPIDocument(doc) @@ -242,8 +242,8 @@ paths: {}` corrupt := []byte(`{not valid json!!!}`) info := doc.GetSpecInfo() info.GetSpecJSON() - info.SpecJSON = &badSpecJSON - info.SpecJSONBytes = &corrupt + info.SpecJSON = &badSpecJSON //nolint:staticcheck + info.SpecJSONBytes = &corrupt //nolint:staticcheck valid, errors := ValidateOpenAPIDocument(doc) @@ -434,8 +434,8 @@ info: // Simulate the nil SpecJSON scenario by setting both to nil info := doc.GetSpecInfo() info.GetSpecJSON() - info.SpecJSON = nil - info.SpecJSONBytes = nil + info.SpecJSON = nil //nolint:staticcheck + info.SpecJSONBytes = nil //nolint:staticcheck // validate! valid, errors := ValidateOpenAPIDocument(doc) @@ -514,8 +514,8 @@ func TestValidateDocument_SpecJSONBytesPath(t *testing.T) { info.GetSpecJSON() // Nil out SpecJSON but leave SpecJSONBytes intact — forces the SpecJSONBytes path - assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") - info.SpecJSON = nil + assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") //nolint:staticcheck + info.SpecJSON = nil //nolint:staticcheck valid, errs := ValidateOpenAPIDocument(doc) assert.True(t, valid) @@ -533,8 +533,8 @@ func TestValidateDocument_SpecJSONBytesCorrupt_NilSpecJSON(t *testing.T) { // and nil out SpecJSON so the fallback normalizeJSON path is skipped. // This exercises the nil guard on SpecJSON inside the error branch. corrupt := []byte(`{not valid json!!!}`) - info.SpecJSONBytes = &corrupt - info.SpecJSON = nil + info.SpecJSONBytes = &corrupt //nolint:staticcheck + info.SpecJSON = nil //nolint:staticcheck // Validation should fail before JSON Schema validation instead of validating nil. valid, errs := ValidateOpenAPIDocument(doc) @@ -554,7 +554,7 @@ func TestValidateDocument_SpecJSONBytesCorrupt_FallbackToSpecJSON(t *testing.T) // Put corrupt bytes in SpecJSONBytes so UnmarshalJSON fails, // but leave SpecJSON intact so the fallback to normalizeJSON executes. corrupt := []byte(`{not valid json!!!}`) - info.SpecJSONBytes = &corrupt + info.SpecJSONBytes = &corrupt //nolint:staticcheck // Should still validate successfully via the SpecJSON fallback valid, errs := ValidateOpenAPIDocument(doc) @@ -570,8 +570,8 @@ func TestValidateDocument_SpecJSONBytesPath_Invalid(t *testing.T) { info.GetSpecJSON() // Nil out SpecJSON but leave SpecJSONBytes intact - assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") - info.SpecJSON = nil + assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") //nolint:staticcheck + info.SpecJSON = nil //nolint:staticcheck valid, errs := ValidateOpenAPIDocument(doc) assert.False(t, valid) From 52417b537d97233010fc3ab3f1ccb675852b221c Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 15 Jun 2026 17:49:49 -0400 Subject: [PATCH 3/3] style: fix gofumpt formatting for inline comments --- schema_validation/validate_document_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/schema_validation/validate_document_test.go b/schema_validation/validate_document_test.go index 6e144dc..dc7a56a 100644 --- a/schema_validation/validate_document_test.go +++ b/schema_validation/validate_document_test.go @@ -242,7 +242,7 @@ paths: {}` corrupt := []byte(`{not valid json!!!}`) info := doc.GetSpecInfo() info.GetSpecJSON() - info.SpecJSON = &badSpecJSON //nolint:staticcheck + info.SpecJSON = &badSpecJSON //nolint:staticcheck info.SpecJSONBytes = &corrupt //nolint:staticcheck valid, errors := ValidateOpenAPIDocument(doc) @@ -515,7 +515,7 @@ func TestValidateDocument_SpecJSONBytesPath(t *testing.T) { // Nil out SpecJSON but leave SpecJSONBytes intact — forces the SpecJSONBytes path assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") //nolint:staticcheck - info.SpecJSON = nil //nolint:staticcheck + info.SpecJSON = nil //nolint:staticcheck valid, errs := ValidateOpenAPIDocument(doc) assert.True(t, valid) @@ -534,7 +534,7 @@ func TestValidateDocument_SpecJSONBytesCorrupt_NilSpecJSON(t *testing.T) { // This exercises the nil guard on SpecJSON inside the error branch. corrupt := []byte(`{not valid json!!!}`) info.SpecJSONBytes = &corrupt //nolint:staticcheck - info.SpecJSON = nil //nolint:staticcheck + info.SpecJSON = nil //nolint:staticcheck // Validation should fail before JSON Schema validation instead of validating nil. valid, errs := ValidateOpenAPIDocument(doc) @@ -571,7 +571,7 @@ func TestValidateDocument_SpecJSONBytesPath_Invalid(t *testing.T) { // Nil out SpecJSON but leave SpecJSONBytes intact assert.NotNil(t, info.SpecJSONBytes, "SpecJSONBytes should be populated by libopenapi") //nolint:staticcheck - info.SpecJSON = nil //nolint:staticcheck + info.SpecJSON = nil //nolint:staticcheck valid, errs := ValidateOpenAPIDocument(doc) assert.False(t, valid)