Skip to content

Commit b82cfa5

Browse files
committed
fix: additionalItems must be ignored when items != array
1 parent df7ca99 commit b82cfa5

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

src/SchemaNode.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,18 @@ export interface SchemaNode extends SchemaNodeMethodsType {
114114
$id?: string;
115115
$defs?: Record<string, SchemaNode>;
116116
$ref?: string;
117-
/** only used for draft <= 2019-09 */
117+
/**
118+
* # Items-object schema for additional items for drafts <= 2019-09
119+
*
120+
* - `additionalItems` is ignored when items-schema is not an array
121+
*
122+
* If `items` is present, and its annotation result is a number, validation succeeds if every
123+
* instance element at an index greater than that number validates against "additionalItems".
124+
* Otherwise, if `items` is absent or its annotation result is the boolean true,
125+
* `additionalItems` is ignored.
126+
*
127+
* [Specification](https://json-schema.org/draft/2019-09/draft-handrews-json-schema-02#additionalItems)
128+
*/
118129
additionalItems?: SchemaNode;
119130
additionalProperties?: SchemaNode;
120131
allOf?: SchemaNode[];
@@ -124,7 +135,39 @@ export interface SchemaNode extends SchemaNodeMethodsType {
124135
dependentSchemas?: Record<string, SchemaNode | boolean>;
125136
else?: SchemaNode;
126137
if?: SchemaNode;
138+
/**
139+
* # Items-array schema for all drafts
140+
*
141+
* - for drafts prior 2020-12 items[]-schema stored as `prefixItems`
142+
*
143+
* Validation succeeds if each element of the instance validates against the schema at the
144+
* same position, if any.
145+
*
146+
* The `prefixItems` keyword restricts a number of items from the start of an array instance
147+
* to validate against the given sequence of subschemas, where the item at a given index in
148+
* the array instance is evaluated against the subschema at the given index in the `prefixItems`
149+
* array, if any. Array items outside the range described by the `prefixItems` keyword is
150+
* evaluated against the items keyword, if present.
151+
*
152+
* [Docs](https://www.learnjsonschema.com/2020-12/applicator/prefixitems/)
153+
* | [Examples](https://json-schema.org/understanding-json-schema/reference/array#tupleValidation)
154+
*/
127155
prefixItems?: SchemaNode[];
156+
/**
157+
* # Items-object schema
158+
*
159+
* - ⚠️ For drafts < 2020-12, `additionalItems` is still used and must be referenced by `node.additionalItems`
160+
*
161+
* Validation succeeds if each element of the instance not covered by `prefixItems` validates
162+
* against this schema.
163+
*
164+
* The items keyword restricts array instance items not described by the sibling `prefixItems`
165+
* keyword (if any), to validate against the given subschema. Whetherthis keyword was evaluated
166+
* against any item of the array instance is reported using annotations.
167+
*
168+
* [Docs](https://www.learnjsonschema.com/2020-12/applicator/items/)
169+
* | [Examples](https://json-schema.org/understanding-json-schema/reference/array#items)
170+
*/
128171
items?: SchemaNode;
129172
not?: SchemaNode;
130173
oneOf?: SchemaNode[];

src/draft2019-09/keywords/additionalItems.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,14 @@ export const additionalItemsKeyword: Keyword = {
1212
addResolve: (node: SchemaNode) => node.additionalItems != null,
1313
resolve: additionalItemsResolver,
1414
addValidate: ({ schema }) =>
15-
schema.additionalItems != null &&
16-
schema.additionalItems !== true &&
17-
schema.items != null &&
18-
!isObject(schema.items),
15+
schema.additionalItems != null && schema.additionalItems !== true && Array.isArray(schema.items),
1916
validate: validateAdditionalItems
2017
};
2118

2219
// must come as last resolver
2320
export function parseAdditionalItems(node: SchemaNode) {
2421
const { schema, evaluationPath, schemaLocation } = node;
25-
if (isObject(schema.additionalItems) || schema.additionalItems === true) {
22+
if ((isObject(schema.additionalItems) || schema.additionalItems === true) && Array.isArray(schema.items)) {
2623
node.additionalItems = node.compileSchema(
2724
schema.additionalItems,
2825
`${evaluationPath}/additionalItems`,

src/draft2019-09/methods/getChildSchemaSelection.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ describe("getChildSelection (2019)", () => {
129129
const result = compileSchema({
130130
$schema: "draft-2019-09",
131131
type: "array",
132+
items: [],
132133
additionalItems: { id: "number", type: "number", default: 2 }
133134
}).getChildSelection(1);
134135

src/draft2019-09/methods/getData.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,7 @@ describe("getData (2019)", () => {
835835
$schema: "draft-2019-09",
836836
type: "array",
837837
minItems: 2,
838+
items: [],
838839
additionalItems: {
839840
type: "number",
840841
default: 2

0 commit comments

Comments
 (0)