Skip to content

Commit

Permalink
Merge 2cd7583 into 45583fd
Browse files Browse the repository at this point in the history
  • Loading branch information
z6n9n committed May 1, 2023
2 parents 45583fd + 2cd7583 commit 628d6e6
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 4 deletions.
5 changes: 5 additions & 0 deletions docs/options.md
Expand Up @@ -177,6 +177,11 @@ Include the reference to the part of the schema (`schema` and `parentSchema`) an

Support [discriminator keyword](./json-schema.md#discriminator) from [OpenAPI specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md).


To bypass the validation exception 'discriminator: mapping is not supported', the following option can be set:

```discriminator: { strict: false }```

### unicodeRegExp

By default Ajv uses unicode flag "u" with "pattern" and "patternProperties", as per JSON Schema spec. See [RegExp.prototype.unicode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode) .
Expand Down
2 changes: 1 addition & 1 deletion lib/core.ts
Expand Up @@ -102,7 +102,7 @@ export interface CurrentOptions {
$data?: boolean
allErrors?: boolean
verbose?: boolean
discriminator?: boolean
discriminator?: boolean | {strict: boolean}
unicodeRegExp?: boolean
timestamp?: "string" | "date" // JTD only
parseDate?: boolean // JTD only
Expand Down
11 changes: 9 additions & 2 deletions lib/vocabularies/discriminator/index.ts
Expand Up @@ -21,15 +21,17 @@ const def: CodeKeywordDefinition = {
type: "object",
schemaType: "object",
error,
code(cxt: KeywordCxt) {
code: function (cxt: KeywordCxt) {
const {gen, data, schema, parentSchema, it} = cxt
const {oneOf} = parentSchema
if (!it.opts.discriminator) {
throw new Error("discriminator: requires discriminator option")
}
const tagName = schema.propertyName
if (typeof tagName != "string") throw new Error("discriminator: requires propertyName")
if (schema.mapping) throw new Error("discriminator: mapping is not supported")
if (schema.mapping && strictDiscriminatorValidation()) {
throw new Error("discriminator: mapping is not supported")
}
if (!oneOf) throw new Error("discriminator: requires oneOf keyword")
const valid = gen.let("valid", false)
const tag = gen.const("tag", _`${data}${getProperty(tagName)}`)
Expand All @@ -40,6 +42,11 @@ const def: CodeKeywordDefinition = {
)
cxt.ok(valid)

function strictDiscriminatorValidation(): boolean {
if (it.opts.discriminator instanceof Object) return it.opts.discriminator.strict
return true
}

function validateMapping(): void {
const mapping = getMapping()
gen.if(false)
Expand Down
53 changes: 52 additions & 1 deletion spec/discriminator.spec.ts
Expand Up @@ -19,7 +19,7 @@ describe("discriminator keyword", function () {
})

function getAjvs(AjvClass: typeof AjvCore) {
return withStandalone(getAjvInstances(AjvClass, options, {discriminator: true}))
return withStandalone(getAjvInstances(AjvClass, options, {discriminator: {strict: false}}))
}

describe("validation", () => {
Expand Down Expand Up @@ -159,6 +159,57 @@ describe("discriminator keyword", function () {
})
})

describe("validation with referenced schemas and mapping", () => {
const definitions1 = {
schema1: {
properties: {
foo: {const: "x"},
a: {type: "string"},
},
required: ["foo", "a"],
},
schema2: {
properties: {
foo: {enum: ["y", "z"]},
b: {type: "string"},
},
required: ["foo", "b"],
},
}
const mainSchema1 = {
type: "object",
discriminator: {
propertyName: "foo",
mapping: {
x: "#/definitions/schema1",
z: "#/definitions/schema2",
},
},
oneOf: [
{
$ref: "#/definitions/schema1",
},
{
$ref: "#/definitions/schema2",
},
],
}

const schema = [{definitions: definitions1, ...mainSchema1}]

it("should validate data", () => {
assertValid(schema, {foo: "x", a: "a"})
assertValid(schema, {foo: "y", b: "b"})
assertValid(schema, {foo: "z", b: "b"})
assertInvalid(schema, {})
assertInvalid(schema, {foo: 1})
assertInvalid(schema, {foo: "bar"})
assertInvalid(schema, {foo: "x", b: "b"})
assertInvalid(schema, {foo: "y", a: "a"})
assertInvalid(schema, {foo: "z", a: "a"})
})
})

describe("validation with deeply referenced schemas", () => {
const schema = [
{
Expand Down

0 comments on commit 628d6e6

Please sign in to comment.