如何在JSON Schema中指定数组类型的顺序、数量并支持嵌套验证
实现方案:用oneOf或if/then验证自定义JSON结构
完全可以通过oneOf或者if/then组合实现你的验证需求,下面分两种方式说明:
方式一:用oneOf枚举所有合法结构
这种方式最直观,直接列出内层数组所有允许的类型组合,同时结合根数组的非空要求:
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "minItems": 1, // 根数组至少1个元素,排除空根数组 "items": { "type": "array", "oneOf": [ // 情况1:仅[string] { "prefixItems": [{ "type": "string" }], "maxItems": 1 }, // 情况2:仅[string, boolean] { "prefixItems": [ { "type": "string" }, { "type": "boolean" } ], "maxItems": 2 }, // 情况3:仅[string, boolean, string] { "prefixItems": [ { "type": "string" }, { "type": "boolean" }, { "type": "string" } ], "maxItems": 3 }, // 情况4:[string, 根结构数组] { "prefixItems": [ { "type": "string" }, { "$ref": "#" } // 引用根结构,保证嵌套数组符合要求 ], "maxItems": 2 }, // 情况5:[string, boolean, 根结构数组] { "prefixItems": [ { "type": "string" }, { "type": "boolean" }, { "$ref": "#" } ], "maxItems": 3 }, // 情况6:[string, boolean, string, 根结构数组] { "prefixItems": [ { "type": "string" }, { "type": "boolean" }, { "type": "string" }, { "$ref": "#" } ], "maxItems": 4 } ] } }
关键说明:
minItems: 1直接排除空根数组;- 每个
oneOf选项严格限制数组长度和对应位置的类型,解决你之前无法验证顺序和数量的问题; - 嵌套的根结构通过
$ref: "#"引用,而根结构本身要求minItems:1,所以像[string, []]这种空数组会被自动排除(因为空数组不符合根结构的minItems要求)。
方式二:用if/then组合实现逻辑递进
如果偏好逻辑判断的写法,也可以用if/then按数组长度分情况验证:
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "minItems": 1, "items": { "type": "array", // 长度为1:必须是[string] "if": { "minItems": 1, "maxItems": 1 }, "then": { "prefixItems": [{ "type": "string" }] }, "else": { // 长度为2:第一个是string,第二个是boolean或根结构数组 "if": { "minItems": 2, "maxItems": 2 }, "then": { "prefixItems": [ { "type": "string" }, { "oneOf": [{ "type": "boolean" }, { "$ref": "#" }] } ] }, "else": { // 长度为3:前两个是string+boolean,第三个是string或根结构数组 "if": { "minItems": 3, "maxItems": 3 }, "then": { "prefixItems": [ { "type": "string" }, { "type": "boolean" }, { "oneOf": [{ "type": "string" }, { "$ref": "#" }] } ] }, "else": { // 长度为4:前三个是string+boolean+string,第四个是根结构数组 "if": { "minItems": 4, "maxItems": 4 }, "then": { "prefixItems": [ { "type": "string" }, { "type": "boolean" }, { "type": "string" }, { "$ref": "#" } ] }, // 其他长度直接不合法 "else": false } } } } }
对比:
oneOf写法更清晰,所有合法结构一目了然,适合你这种有限的类型组合场景;if/then写法更偏向逻辑流程,适合后续可能扩展更多长度规则的情况。
两种方案都能满足你的所有验证要求:限制内层数组的类型顺序和数量、允许嵌套根结构、排除空根数组和[string, []]这类非法结构。
内容的提问来源于stack exchange,提问作者Ero
相关产品推荐
相关产品推荐

