Skip to content

Commit

Permalink
fix JTD discriminator with more than 8 properties, fixes #1971 (#2194)
Browse files Browse the repository at this point in the history
* fix JTD discriminator with more than 8 properties, fixes #1971

* prettier
  • Loading branch information
epoberezkin authored Jan 3, 2023
1 parent 527d43a commit c5c195b
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 6 deletions.
19 changes: 13 additions & 6 deletions lib/vocabularies/jtd/properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,7 @@ export function validateProperties(cxt: KeywordCxt): void {

function validateAdditional(): void {
gen.forIn("key", data, (key: Name) => {
const _allProps =
it.jtdDiscriminator === undefined ? allProps : [it.jtdDiscriminator].concat(allProps)
const addProp = isAdditional(key, _allProps, "properties")
const addProp = isAdditional(key, allProps, "properties", it.jtdDiscriminator)
const addOptProp = isAdditional(key, allOptProps, "optionalProperties")
const extra =
addProp === true ? addOptProp : addOptProp === true ? addProp : and(addProp, addOptProp)
Expand All @@ -159,14 +157,23 @@ export function validateProperties(cxt: KeywordCxt): void {
})
}

function isAdditional(key: Name, props: string[], keyword: string): Code | true {
function isAdditional(
key: Name,
props: string[],
keyword: string,
jtdDiscriminator?: string
): Code | true {
let additional: Code | boolean
if (props.length > 8) {
// TODO maybe an option instead of hard-coded 8?
const propsSchema = schemaRefOrVal(it, parentSchema[keyword], keyword)
additional = not(isOwnProperty(gen, propsSchema as Code, key))
} else if (props.length) {
additional = and(...props.map((p) => _`${key} !== ${p}`))
if (jtdDiscriminator !== undefined) {
additional = and(additional, _`${key} !== ${jtdDiscriminator}`)
}
} else if (props.length || jtdDiscriminator !== undefined) {
const ps = jtdDiscriminator === undefined ? props : [jtdDiscriminator].concat(props)
additional = and(...ps.map((p) => _`${key} !== ${p}`))
} else {
additional = true
}
Expand Down
61 changes: 61 additions & 0 deletions spec/issues/1971_jtd_discriminator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import _Ajv from "../ajv_jtd"
import * as assert from "assert"

describe("JTD discriminator with more than 8 (hardcoded in properties.ts) properties (issue #1971)", () => {
const ajv = new _Ajv()

it("should correctly validate empty values form", () => {
const schema = {
discriminator: "tag",
mapping: {
manual: {
properties: {
first: {type: "uint16"},
second: {type: "uint16"},
third: {type: "uint16"},
fourth: {type: "uint16"},
fifth: {type: "uint16"},
sixth: {type: "uint16"},
additionalOne: {type: "uint16"},
additionalTwo: {type: "uint16"},
},
},
auto: {
properties: {
first: {type: "uint16"},
second: {type: "uint16"},
third: {type: "uint16"},
fourth: {type: "uint16"},
fifth: {type: "uint16"},
sixth: {type: "uint16"},
additionalThree: {type: "uint16"},
},
},
},
}
const data1 = {
tag: "manual",
first: 1,
second: 1,
third: 1,
fourth: 1,
fifth: 1,
sixth: 1,
additionalOne: 1,
additionalTwo: 1,
}
const data2 = {
tag: "auto",
first: 1,
second: 1,
third: 1,
fourth: 1,
fifth: 1,
sixth: 1,
additionalThree: 1,
}
const validate = ajv.compile(schema)
assert.strictEqual(validate(data1), true)
assert.strictEqual(validate(data2), true)
})
})

1 comment on commit c5c195b

@Dawidowak
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O

Please sign in to comment.