diff --git a/draft.go b/draft.go index f40173d..b165a93 100644 --- a/draft.go +++ b/draft.go @@ -273,6 +273,41 @@ func (d *dialect) hasVocab(name string) bool { return slices.Contains(d.draft.defaultVocabs, name) } +func (d *dialect) getSchema() *Schema { + if d.vocabs == nil { + return d.draft.sch + } + // TODO: support custom vocabulary + var allOf []*Schema + for _, vocab := range d.vocabs { + sch := d.draft.allVocabs[vocab] + if sch != nil { + allOf = append(allOf, sch) + } + } + if !slices.Contains(d.vocabs, "core") { + sch := d.draft.allVocabs["core"] + if sch == nil { + sch = d.draft.sch + } + allOf = append(allOf, sch) + } + sch := &Schema{ + Location: "urn:mem:metaschema", + up: urlPtr{url("urn:mem:metaschema"), ""}, + DraftVersion: d.draft.version, + AllOf: allOf, + } + sch.resource = sch + if sch.DraftVersion >= 2020 { + sch.DynamicAnchor = "meta" + sch.dynamicAnchors = map[string]*Schema{ + "meta": sch, + } + } + return sch +} + // -- type ParseIDError struct { diff --git a/root.go b/root.go index 5242c66..0dceacc 100644 --- a/root.go +++ b/root.go @@ -268,24 +268,10 @@ func (r *root) collectAnchors(sch any, schPtr jsonPointer, res *resource) error func (r *root) validate(ptr jsonPointer, v any, regexpEngine RegexpEngine) error { dialect := r.resource(ptr).dialect up := urlPtr{r.url, ptr} - if dialect.vocabs == nil { - meta := dialect.draft.sch - if err := meta.validate(v, regexpEngine, meta, r.resources); err != nil { - return &SchemaValidationError{URL: up.String(), Err: err} - } - return nil - } - - // TODO: validate with vocabs with metaswitch - // validate only with the vocabs listed in metaschema - if err := dialect.draft.allVocabs["core"].validate(v, regexpEngine, nil, nil); err != nil { + meta := dialect.getSchema() + if err := meta.validate(v, regexpEngine, meta, r.resources); err != nil { return &SchemaValidationError{URL: up.String(), Err: err} } - for _, vocab := range dialect.vocabs { - if err := dialect.draft.allVocabs[vocab].validate(v, regexpEngine, nil, nil); err != nil { - return &SchemaValidationError{URL: up.String(), Err: err} - } - } return nil } diff --git a/testdata/Extra-Test-Suite/tests/draft2020-12/mixed-dialects.json b/testdata/Extra-Test-Suite/tests/draft2020-12/mixed-dialects.json index 175e3ec..b517e87 100644 --- a/testdata/Extra-Test-Suite/tests/draft2020-12/mixed-dialects.json +++ b/testdata/Extra-Test-Suite/tests/draft2020-12/mixed-dialects.json @@ -33,5 +33,35 @@ "valid": false } ] + }, + { + "description": "subschema without applicator", + "schema": { + "$defs": { + "one": { + "$id": "http://temp.com/one.json", + "$schema": "http://localhost:1234/draft2020-12/no-applicator.json", + "$comment": "should ignore unevaluatedProperties", + "type": "object", + "allOf": [ + 1, + { "type": "number" } + ] + } + }, + "$ref": "#/$defs/one" + }, + "tests": [ + { + "description": "valid", + "data": {}, + "valid": true + }, + { + "description": "invalid", + "data": 1, + "valid": false + } + ] } ] diff --git a/validator.go b/validator.go index 9f3d45d..d14ae17 100644 --- a/validator.go +++ b/validator.go @@ -283,7 +283,7 @@ func (vd *validator) objValidate(obj map[string]any) { sch, meta, resources := s.PropertyNames, vd.meta, vd.resources res := vd.metaResource(sch) if res != nil { - meta = res.dialect.draft.sch + meta = res.dialect.getSchema() sch = meta } if err := sch.validate(pname, vd.regexpEngine, meta, resources); err != nil { @@ -493,7 +493,7 @@ func (vd *validator) strValidate(str string) { sch, meta, resources := s.ContentSchema, vd.meta, vd.resources res := vd.metaResource(sch) if res != nil { - meta = res.dialect.draft.sch + meta = res.dialect.getSchema() sch = meta } if err = sch.validate(*deserialized, vd.regexpEngine, meta, resources); err != nil { @@ -710,7 +710,7 @@ func (vd *validator) handleMeta() { if res == nil { return } - sch := res.dialect.draft.sch + sch := res.dialect.getSchema() vd.meta = sch vd.sch = sch }