Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
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
github.com/dlclark/regexp2 v1.12.0
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
)

Expand All @@ -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
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand All @@ -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=
Expand All @@ -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=
Expand Down
14 changes: 7 additions & 7 deletions schema_validation/validate_document.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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()),
Expand All @@ -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()),
Expand Down
35 changes: 22 additions & 13 deletions schema_validation/validate_document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,8 +210,9 @@ paths: {}`
},
}
info := doc.GetSpecInfo()
info.SpecJSON = &badSpecJSON
info.SpecJSONBytes = nil
info.GetSpecJSON()
info.SpecJSON = &badSpecJSON //nolint:staticcheck
info.SpecJSONBytes = nil //nolint:staticcheck

valid, errors := ValidateOpenAPIDocument(doc)

Expand Down Expand Up @@ -240,8 +241,9 @@ paths: {}`
}
corrupt := []byte(`{not valid json!!!}`)
info := doc.GetSpecInfo()
info.SpecJSON = &badSpecJSON
info.SpecJSONBytes = &corrupt
info.GetSpecJSON()
info.SpecJSON = &badSpecJSON //nolint:staticcheck
info.SpecJSONBytes = &corrupt //nolint:staticcheck

valid, errors := ValidateOpenAPIDocument(doc)

Expand Down Expand Up @@ -431,8 +433,9 @@ info:

// Simulate the nil SpecJSON scenario by setting both to nil
info := doc.GetSpecInfo()
info.SpecJSON = nil
info.SpecJSONBytes = nil
info.GetSpecJSON()
info.SpecJSON = nil //nolint:staticcheck
info.SpecJSONBytes = nil //nolint:staticcheck

// validate!
valid, errors := ValidateOpenAPIDocument(doc)
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -506,10 +511,11 @@ 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")
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)
Expand All @@ -521,13 +527,14 @@ 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.
// 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)
Expand All @@ -542,11 +549,12 @@ 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.
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)
Expand All @@ -559,10 +567,11 @@ 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")
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)
Expand Down
Loading