Skip to content

Commit c80e0ae

Browse files
committedJan 21, 2024
[Bugfix] Fix complex intersections of allOf/anyOf/properties/required (fix #381)
1 parent 6adcad9 commit c80e0ae

8 files changed

+1339
-101
lines changed
 

‎src/normalizer.ts

+14
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,20 @@ rules.set('Transform const to singleton enum', schema => {
222222
}
223223
})
224224

225+
// @see https://json-schema.org/understanding-json-schema/reference/combining#factoring-schemas
226+
rules.set('Propagate additionalProperties=false to all factors', schema => {
227+
const parent = schema[Parent]
228+
if (!parent || parent.additionalProperties !== false) {
229+
return
230+
}
231+
232+
if (schema.hasOwnProperty('additionalProperties')) {
233+
return
234+
}
235+
236+
schema.additionalProperties = false
237+
})
238+
225239
export function normalize(
226240
rootSchema: LinkedJSONSchema,
227241
dereferencedPaths: DereferencedPaths,

‎src/typesOfSchema.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,14 @@ const matchers: Record<SchemaType, (schema: JSONSchema) => boolean> = {
140140
}
141141
return 'enum' in schema
142142
},
143-
UNNAMED_SCHEMA() {
144-
return false // Explicitly handled as the default case
143+
UNNAMED_SCHEMA(schema) {
144+
return Boolean(
145+
!('$id' in schema) &&
146+
(schema.patternProperties?.length ||
147+
schema.properties?.length ||
148+
// TODO: fix the typing
149+
(schema.required as string[])?.length),
150+
)
145151
},
146152
UNTYPED_ARRAY(schema) {
147153
return schema.type === 'array' && !('items' in schema)

‎test/__snapshots__/test/test.ts.md

+1,266-98
Large diffs are not rendered by default.

‎test/__snapshots__/test/test.ts.snap

1.03 KB
Binary file not shown.

‎test/e2e/allOf.properties.1.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export const input = {
2+
type: 'object',
3+
properties: {
4+
a: {type: 'string'},
5+
b: {type: 'string'},
6+
c: {type: 'string'},
7+
},
8+
allOf: [
9+
{required: ['a']},
10+
{
11+
oneOf: [{required: ['b']}, {required: ['c']}],
12+
},
13+
],
14+
additionalProperties: false,
15+
}

‎test/e2e/allOf.properties.2.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export const input = {
2+
type: 'object',
3+
properties: {
4+
a: {type: 'string'},
5+
b: {type: 'string'},
6+
c: {type: 'string'},
7+
},
8+
allOf: [
9+
{required: ['a']},
10+
{
11+
oneOf: [{required: ['b']}, {required: ['c']}],
12+
},
13+
],
14+
}

‎test/e2e/allOf.properties.3.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export const input = {
2+
type: 'object',
3+
properties: {
4+
a: {type: 'string'},
5+
b: {type: 'string'},
6+
c: {type: 'string'},
7+
},
8+
allOf: [
9+
{required: ['a']},
10+
{
11+
oneOf: [
12+
{required: ['b']},
13+
// Non-existent property is invalid, but it's not up to JSTT to validate this
14+
// "An object instance is valid against this keyword if every
15+
// item in the array is the name of a property in the instance."
16+
// @see https://json-schema.org/draft/2020-12/json-schema-validation#name-required
17+
{required: ['d']},
18+
],
19+
},
20+
],
21+
}

‎test/e2e/allOf.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const input = {
2121
a: {type: 'string'},
2222
},
2323
additionalProperties: false,
24-
required: ['a', 'b'],
24+
required: ['a'],
2525
},
2626
},
2727
required: ['foo', 'bar'],

0 commit comments

Comments
 (0)
Failed to load comments.