diff --git a/go.mod b/go.mod index eef097dc..c39ab60b 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,8 @@ require ( atomicgo.dev/cursor v0.2.0 // indirect atomicgo.dev/keyboard v0.2.9 // indirect atomicgo.dev/schedule v0.1.0 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/containerd/console v1.0.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlclark/regexp2 v1.10.0 // indirect @@ -40,6 +42,7 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -54,6 +57,7 @@ require ( github.com/spf13/afero v1.10.0 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.3.0 // indirect @@ -63,3 +67,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) + +replace github.com/pb33f/libopenapi => github.com/speakeasy-api/libopenapi v0.0.0-20231203222815-69ba5b875a1d + +replace github.com/pb33f/libopenapi-validator => github.com/speakeasy-api/libopenapi-validator v0.0.0-20231203225248-8ab40e19ca43 diff --git a/go.sum b/go.sum index a74fe5da..ed21a321 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,10 @@ github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= @@ -194,6 +198,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -218,6 +223,8 @@ github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8 github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -248,10 +255,6 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/pb33f/libopenapi v0.13.20 h1:u07mWNSL30sO8nj+kRjM9mDcqxOxq+Etso/oUFflvU4= -github.com/pb33f/libopenapi v0.13.20/go.mod h1:Lv2eEtsAtbRFlF8hjH82L8SIGoUNgemMVoKoB6A9THk= -github.com/pb33f/libopenapi-validator v0.0.32 h1:jM+IsUT8I0JOtdkgacGVQmTJayQ2AO5P6URI2HxN11g= -github.com/pb33f/libopenapi-validator v0.0.32/go.mod h1:1HbsnP1IVFEaLFtbK9eZXRqUpvtQEGmdstqbgMG+72A= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -288,6 +291,10 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/speakeasy-api/libopenapi v0.0.0-20231203222815-69ba5b875a1d h1:rPCPao2+13LBlaGrXpI3r76i2qDK6tQL4mOG98yQ+gk= +github.com/speakeasy-api/libopenapi v0.0.0-20231203222815-69ba5b875a1d/go.mod h1:m+4Pwri31UvcnZjuP8M7TlbR906DXJmMvYsbis234xg= +github.com/speakeasy-api/libopenapi-validator v0.0.0-20231203225248-8ab40e19ca43 h1:BOZvakIzJpR4/o1UmDJ9PQ5SKDED8Lo3KWuYWWn8Z4o= +github.com/speakeasy-api/libopenapi-validator v0.0.0-20231203225248-8ab40e19ca43/go.mod h1:inrPaI2H70ISsxdv6m1Frf87TzRhltRe6SfuHyMdd4k= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= @@ -314,6 +321,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= diff --git a/parser/json_schema.go b/parser/json_schema.go index ad9cf7b7..5e34b450 100644 --- a/parser/json_schema.go +++ b/parser/json_schema.go @@ -8,6 +8,9 @@ import ( "encoding/json" "errors" "fmt" + "strings" + "time" + "github.com/daveshanley/vacuum/model" yamlAlt "github.com/ghodss/yaml" validationErrors "github.com/pb33f/libopenapi-validator/errors" @@ -16,10 +19,9 @@ import ( "github.com/pb33f/libopenapi/datamodel/low" lowBase "github.com/pb33f/libopenapi/datamodel/low/base" "github.com/pb33f/libopenapi/index" + "github.com/pb33f/libopenapi/orderedmap" "github.com/pb33f/libopenapi/utils" "gopkg.in/yaml.v3" - "strings" - "time" ) type Schema struct { @@ -63,8 +65,10 @@ type ExampleValidation struct { // value that has been set. func ValidateExample(jc *highBase.Schema) []*ExampleValidation { var examples []*ExampleValidation - if len(jc.Properties) > 0 { - for propName, prop := range jc.Properties { + if orderedmap.Len(jc.Properties) > 0 { + for pair := orderedmap.First(jc.Properties); pair != nil; pair = pair.Next() { + propName := pair.Key() + prop := pair.Value() sc := prop.Schema() if sc.Type != nil && sc.Example != nil { @@ -75,19 +79,22 @@ func ValidateExample(jc *highBase.Schema) []*ExampleValidation { isFloat := false isString := false - if _, ok := sc.Example.(string); ok { + var example any + _ = sc.Example.Decode(&example) + + if _, ok := example.(string); ok { isString = true } - if _, ok := sc.Example.(bool); ok { + if _, ok := example.(bool); ok { isBool = true } - if _, ok := sc.Example.(float64); ok { + if _, ok := example.(float64); ok { isFloat = true } - if _, ok := sc.Example.(int); ok { + if _, ok := example.(int); ok { isInt = true } @@ -122,10 +129,9 @@ func ValidateExample(jc *highBase.Schema) []*ExampleValidation { } } switch sc.Type { - } } else { - if len(sc.Properties) > 0 { + if orderedmap.Len(sc.Properties) > 0 { examples = append(examples, ValidateExample(sc)...) } } @@ -150,7 +156,7 @@ func ConvertNodeIntoJSONSchema(node *yaml.Node, idx *index.SpecIndex) (*highBase return nil, mbErr } - var path = "" + path := "" isRef, _, ref := utils.IsNodeRefValue(node) if isRef { @@ -181,7 +187,6 @@ func ConvertNodeIntoJSONSchema(node *yaml.Node, idx *index.SpecIndex) (*highBase // ConvertNodeDefinitionIntoSchema will convert any definition node (components, params, etc.) into a standard // Schema that can be used with JSONSchema. This will auto-timeout of th func ConvertNodeDefinitionIntoSchema(node *yaml.Node) (*Schema, error) { - schChan := make(chan Schema, 1) errChan := make(chan error, 1) @@ -216,8 +221,7 @@ func ConvertNodeDefinitionIntoSchema(node *yaml.Node) (*Schema, error) { // ValidateNodeAgainstSchema will accept a schema and a node and check it's valid and return the result, or error. func ValidateNodeAgainstSchema(ctx *model.RuleFunctionContext, schema *highBase.Schema, node *yaml.Node, isArray bool) (bool, []*validationErrors.ValidationError) { - - //convert node to raw yaml first, then convert to json to be used in schema validation + // convert node to raw yaml first, then convert to json to be used in schema validation var d []byte var e error if !isArray {