如何在 JSON 模式验证器中表示联合类型?
How to represent union types in JSON schema validator?
我是 JSON 模式验证的新手,我正在为配置构建自定义模式。我正在构建的架构基于 Typescript 类型。我了解如何验证简单的数据类型,如数组、对象、数字、字符串等。
但是有没有办法像这样指定类型:
type Conf = {
idle_session_timeout?: number | "none",
item: {
kind: "attribute";
name: string;
} | {
kind: "relation";
name: string;
} | {
kind: "group";
name: string;
label?: string | undefined;
entries: PresentationItem[];
}
order_by: string | {
attribute: string;
direction?: "asc" | "desc" | undefined;
}
}
我从http://json-schema.org/draft-07/schema注意到它支持if then else语句根据值切换验证模式,但我不知道如何实现它们。
有几个关键字需要注意,可能参考以下规范:
首先,"type"允许在一个数组中指定多个值。有了这个,您可以指定例如["string", "number"]
表示 "string or number." 许多关键字只适用于特定 JSON 类型的实例。作为一项规则,您可以将一个 "type" 的架构和另一个 "type" 的架构组合在一起,前提是所有剩余的关键字仅适用于各自的类型。
例如,您可以有两个模式,例如:
{
"type": "string",
"minLength": 1
}
{
"type": "number",
"minimum": 0
}
而且因为"minimum"只适用于数字,而"minLength"只适用于字符串,你可以简单地将模式组合在一起,它会产生相同的效果:
{
"type": ["string", "number"],
"minLength": 1
"minimum": 0
}
但是,对于相同 "type" 的两个模式,这样做将执行 交集 而不是联合。这是因为将关键字添加到 JSON 模式会增加约束,而将值添加到 "type" 列表 会删除 约束(更多值变得有效)。
因此,如果您对相同 "type" 的两个模式执行联合,或者如果您将模式与验证所有类型(特别是 "enum" 或 "const" 的关键字组合),您需要将它们与 "anyOf" 关键字组合,该关键字对多个模式的数组执行联合。 (你也可以考虑"oneOf"。)
我想你最终会得到这样的模式:
{
"type": "object",
"properties": {
"idle_session_timeout": {
"type": ["number","string"],
"anyOf": [ {"type":"number"}, {"const":"none"} ]
},
"item": {
"type": "object",
"required": ["kind", "name"],
"properties": {
"kind": { "type": "string" },
"name": { "type": "string" },
},
"anyOf": [
{
"properties": {
"kind": { "const": "attribute" },
}
},
{
"properties": {
"kind": { "const": "relation" },
}
},
{
"required": ["entries"],
"properties": {
"kind": { "const": "group" },
"label": { "type": "string" },
"entries": { "type":"array", "items": {"$ref":"PresentationItem"} },
}
}
]
},
"order_by": {
"type": ["string", "object"],
"required": ["attribute"],
"properties": {
"attribute": { "type": "string" },
"direction": { "enum": ["asc", "desc"] },
}
}
}
请注意我是如何将 "anyOf" 中的常见关键字提取到可能的最高级别的。这是一种风格选择。它会产生更清晰的错误,但它可能与您无关,具体取决于您计划如何扩展架构。
我是 JSON 模式验证的新手,我正在为配置构建自定义模式。我正在构建的架构基于 Typescript 类型。我了解如何验证简单的数据类型,如数组、对象、数字、字符串等。
但是有没有办法像这样指定类型:
type Conf = {
idle_session_timeout?: number | "none",
item: {
kind: "attribute";
name: string;
} | {
kind: "relation";
name: string;
} | {
kind: "group";
name: string;
label?: string | undefined;
entries: PresentationItem[];
}
order_by: string | {
attribute: string;
direction?: "asc" | "desc" | undefined;
}
}
我从http://json-schema.org/draft-07/schema注意到它支持if then else语句根据值切换验证模式,但我不知道如何实现它们。
有几个关键字需要注意,可能参考以下规范:
首先,"type"允许在一个数组中指定多个值。有了这个,您可以指定例如["string", "number"]
表示 "string or number." 许多关键字只适用于特定 JSON 类型的实例。作为一项规则,您可以将一个 "type" 的架构和另一个 "type" 的架构组合在一起,前提是所有剩余的关键字仅适用于各自的类型。
例如,您可以有两个模式,例如:
{
"type": "string",
"minLength": 1
}
{
"type": "number",
"minimum": 0
}
而且因为"minimum"只适用于数字,而"minLength"只适用于字符串,你可以简单地将模式组合在一起,它会产生相同的效果:
{
"type": ["string", "number"],
"minLength": 1
"minimum": 0
}
但是,对于相同 "type" 的两个模式,这样做将执行 交集 而不是联合。这是因为将关键字添加到 JSON 模式会增加约束,而将值添加到 "type" 列表 会删除 约束(更多值变得有效)。
因此,如果您对相同 "type" 的两个模式执行联合,或者如果您将模式与验证所有类型(特别是 "enum" 或 "const" 的关键字组合),您需要将它们与 "anyOf" 关键字组合,该关键字对多个模式的数组执行联合。 (你也可以考虑"oneOf"。)
我想你最终会得到这样的模式:
{
"type": "object",
"properties": {
"idle_session_timeout": {
"type": ["number","string"],
"anyOf": [ {"type":"number"}, {"const":"none"} ]
},
"item": {
"type": "object",
"required": ["kind", "name"],
"properties": {
"kind": { "type": "string" },
"name": { "type": "string" },
},
"anyOf": [
{
"properties": {
"kind": { "const": "attribute" },
}
},
{
"properties": {
"kind": { "const": "relation" },
}
},
{
"required": ["entries"],
"properties": {
"kind": { "const": "group" },
"label": { "type": "string" },
"entries": { "type":"array", "items": {"$ref":"PresentationItem"} },
}
}
]
},
"order_by": {
"type": ["string", "object"],
"required": ["attribute"],
"properties": {
"attribute": { "type": "string" },
"direction": { "enum": ["asc", "desc"] },
}
}
}
请注意我是如何将 "anyOf" 中的常见关键字提取到可能的最高级别的。这是一种风格选择。它会产生更清晰的错误,但它可能与您无关,具体取决于您计划如何扩展架构。