oneOf matches more than one #ref or Property
when i try to test oneOf under reference object, it matches single individual input data with all the schemas under oneOf and giving error as below.
request body has an error: doesn't match the schema: input matches more than one oneOf schemas
verrsion i have used
github.com/getkin/kin-openapi v0.63.0
yaml i have used attached
openapi: 3.0.0 info: title: test 123 description: description contact: email: [email protected] license: name: Apache 2.0 url: http://www.apache.org/licenses/LICENSE-2.0.html version: 1.0.1 tags:
- name: testOneof description: Everything paths: /testOneof: patch: tags: - testOneof summary: modify subscriber in network elements description: | This API is used to create operationId: testOneof requestBody: content: application/json: schema: $ref: '#/components/schemas/ModifyData' responses: "202": description: Request for .
components:
schemas:
ModifyData:
required:
- '@type'
- neModifyData
type: object
properties:
'@type':
maxLength: 64
minLength: 2
type: string
example: neModifyData
default: neModifyData
neModifyData:
$ref: '#/components/schemas/neModifyData'
neModifyData:
type: object
oneOf:
- properties:
accountStatus:
type: string
description: Account status of this subscriber
example: active
default: active
enum:
- active
- suspended
- properties:
subscriberType:
type: string
enum:
- PRE
- POST
- POST
- HYBRID
- properties:
oneData :
$ref: '#/components/schemas/oneData'
- properties:
twoData:
$ref: '#/components/schemas/twoData'
- properties:
threeData:
$ref: '#/components/schemas/threeData'
oneData:
type: object
properties:
oneDataService:
type: string
minLength: 1
maxLength: 20
twoData:
type: object
properties:
twoDataService:
type: string
minLength: 1
maxLength: 20
threeData:
type: object
properties:
twoDataService:
type: string
minLength: 1
maxLength: 20
securitySchemes: basicAuth: type: http scheme: basic
sample inputs used for testing below. for any oneof data it is giving error.
{ "@type": "neModifyData", "neModifyData": { "accountStatus": "active" } }
{ "@type": "neModifyData", "neModifyData": { "subscriberType": "POST" } }
Golang server code used
`package main
import ( "context" "fmt"
"net/http"
"github.com/getkin/kin-openapi/openapi3"
"github.com/getkin/kin-openapi/openapi3filter"
legacyrouter "github.com/getkin/kin-openapi/routers/legacy"
)
func requestHandler(response http.ResponseWriter, request *http.Request) { fmt.Println("received request") ctx := context.Background() loader := &openapi3.Loader{Context: ctx} doc, _ := loader.LoadFromFile("openapi_modify.yaml") err := doc.Validate(ctx) if err != nil { fmt.Println("doc.Validate Error:", err) return }
router, _ := legacyrouter.NewRouter(doc)
// Find route
route, pathParams, _ := router.FindRoute(request)
// Validate request
requestValidationInput := &openapi3filter.RequestValidationInput{
Request: request,
PathParams: pathParams,
Route: route,
}
if err := openapi3filter.ValidateRequest(ctx, requestValidationInput); err != nil {
fmt.Println("Request Validation Failed!!!", err)
} else {
fmt.Println("Request Validation Success!!!")
}
}
func main() {
http.HandleFunc("/", requestHandler)
http.ListenAndServe(":8090", nil)
} `
Analyzed code with some prints and found issue in visitJSONObject() function in schema.go file
in visitJSONObject function, if it gets the propertyRef it is validating, if the propertyRef is not found then it function would return success all the time.
this function will be called from visitSetOperations for all the oneof schemas, in which for all the schemas it returns success and fianlly visitSerOperations fuction has logic to fail if it is success for all the schema to fail.
visitSetOperations
for k, v := range value { if properties != nil { propertyRef := properties[k] fmt.Printf("visitJSONObject: properties[k] : %v --> %v\n", k, *propertyRef) fmt.Printf("visitJSONObject: v : %v\n", v) if propertyRef != nil { p := propertyRef.Value if p == nil { return foundUnresolvedRef(propertyRef.Ref) } if err := p.visitJSON(settings, v); err != nil { if settings.failfast { return errSchema } err = markSchemaErrorKey(err, k) if !settings.multiError { return err } if v, ok := err.(MultiError); ok { me = append(me, v...) continue } me = append(me, err) } continue } }
visitSetOperations
if v := schema.OneOf; len(v) > 0 { fmt.Println("visitSetOperations schema.OneOf len(v)", len(v)) ok := 0 for _, item := range v { v := item.Value fmt.Println("visitSetOperations value : ", v) if v == nil { return foundUnresolvedRef(item.Ref) } var oldfailfast bool oldfailfast, settings.failfast = settings.failfast, true err := v.visitJSON(settings, value) settings.failfast = oldfailfast if err == nil { fmt.Println("$$$$$$$$$$$ Got Success") if schema.Discriminator != nil { pn := schema.Discriminator.PropertyName if valuemap, okcheck := value.(map[string]interface{}); okcheck { if discriminatorVal, okcheck := valuemap[pn]; okcheck == true { mapref, okcheck := schema.Discriminator.Mapping[discriminatorVal.(string)] if okcheck && mapref == item.Ref { ok++ } } } } else { ok++ } } } fmt.Println("visitSetOperations Ok : ", ok) if ok != 1 { if settings.failfast { return errSchema } e := &SchemaError{ Value: value, Schema: schema, SchemaField: "oneOf", } if ok > 1 { e.Origin = ErrOneOfConflict } return e } }
Questions i have here is
- why visitJSONObject ignoring the fields which are not part of schema. this leads to schema validation success for the input data consist of elements which are not present in schema.
- i have checked commit log, this code is present from beginnig , is it done internsionally?
Solution i could think of
visitJSONObject should fail if propertyRef is not present for the incoming data. if solution looks fine i can push the change if you wish to.
@fenollp pls check this and comment.
At this point there are many issues with this project's own schema validation code. We're looking to replace this code with a third party's lib. Maybe take a look at https://github.com/getkin/kin-openapi/pull/318 but we'll probably use https://github.com/qri-io/jsonschema/
Hi @fenollp , any workaround we have for this issue? if you can estimate how much effort we need on supporting jsonschema may be i can try to contribute.
@fenollp ?
Hi there! Could you send a PR with your changes and a regression test?