如何在单个 JSON 模式上验证输入和输出(只读的边缘情况)
How to validate input and output on a single JSON Schema (edge cases with readOnly)
我的问题与 JSON schema for data description vs data validation vs input validation 有一些重叠,但差异很大,我觉得需要提出一个新问题。
我正在尝试了解设计一种模式的最佳方法,该模式可用于验证单个资源表示的输入和输出。这是一个例子。
{
"type": "object",
"properties": {
"id": {
"type": "number",
"readOnly": true
},
"title": {
"type": "string"
},
"post": {
"type": "string"
}
},
"required": ["id", "title", "post"],
"additionalProperties": false
};
问题是在验证输出时,我们需要 id
、title
和 post
。验证输入时,将不需要一个或多个字段,如果它们提供 id
我希望验证失败(由于 readOnly
关键字)
我认为正确的方法是将 required
与 subschemas or boolean logic 结合使用,但我不确定如何将它们结合在一起。
这是正确的路径,还是有更好的解决方案?有谁有适用于最新版本 JSON Schema(此时草案 7)
的示例
谢谢!
这里有几种可能的方法。
首先,readOnly
永远不会导致 JSON 架构的验证过程失败。这不是一个断言,只是一个注解,应用程序可以根据需要使用它来采取行动。因此,您的服务器应用程序可以随心所欲地处理它 - 如果有人试图更改它,则会引发错误,或者只是默默地忽略新值。
或者查看 HTTP Prefer
header,如果存在 handling=lenient
,请忽略任何更改 read-only 值的尝试,但如果存在 handling=strict
存在,任何尝试都会出错。
或者以不同的方式处理不同的字段。如果你有一个 lastModified
字段并支持 HTTP GET => modify => HTTP PUT 工作流,那么当你 PUT 一个表示时, lastModified
将不可避免地出错但 read-only 在某些时候.您不想因为过时的 auto-generated 时间戳而中断 PUT。但是如果有人认为他们可以更改 id
字段,您可能确实想提出错误。
鉴于此,有两种通用方法:编写一个双向工作的模式并在您的应用程序层中进行额外检查,或者分别确定输入和输出的所有内容。
"works both ways" 方法会从 required
中删除 id
,但请注意,一旦创建,资源将始终具有 id
。但是这样它可以在创建或写入时被省略而不会出现问题。要确定这是否合理,请考虑 client-side 输出验证的用例。客户端是否真的需要 JSON 架构来检查服务器是否发送了 id
,或者客户端是否可以根据文档合理地假设服务器会正确执行?
对于 "lock down each way" 方法,您可以这样做:
{
"definitions": {
"common": {
"type": "object",
"properties": {
"id": {
"type": "number",
"readOnly": true
},
"title": {
"type": "string"
},
"post": {
"type": "string"
}
},
"required": ["title", "post"],
"additionalProperties": false
},
"input": {
"allOf": [
{"$ref": "#/definitions/common"},
{"properties": {"id": false}}
]
},
"output": {
"allOf": [
{"$ref": "#/definitions/common"},
{"required": ["id"]}
]
}
}
}
您需要在公共模式中定义 id
以便 "additionalProperties": false
知道它(我尽量避免 "additionalProperties": false
因为它使得以兼容的方式演化表示变得困难,但是如果你想使用它,这是让它工作的方法。
对于输出,只需要id
。
对于输入,使用{"properties": {"id": false}}
禁用id
。即使它是在 "common" 中定义的,false
布尔模式总是会导致 id
无法通过输入验证。
当然,您必须弄清楚您的应用程序如何知道要使用哪个模式,因为再次 readOnly
其自身永远不会导致验证失败。这是我更喜欢为读取和写入使用一个模式并让应用程序处理差异(并记录该处理如何工作)的原因之一。
我的问题与 JSON schema for data description vs data validation vs input validation 有一些重叠,但差异很大,我觉得需要提出一个新问题。
我正在尝试了解设计一种模式的最佳方法,该模式可用于验证单个资源表示的输入和输出。这是一个例子。
{
"type": "object",
"properties": {
"id": {
"type": "number",
"readOnly": true
},
"title": {
"type": "string"
},
"post": {
"type": "string"
}
},
"required": ["id", "title", "post"],
"additionalProperties": false
};
问题是在验证输出时,我们需要 id
、title
和 post
。验证输入时,将不需要一个或多个字段,如果它们提供 id
我希望验证失败(由于 readOnly
关键字)
我认为正确的方法是将 required
与 subschemas or boolean logic 结合使用,但我不确定如何将它们结合在一起。
这是正确的路径,还是有更好的解决方案?有谁有适用于最新版本 JSON Schema(此时草案 7)
的示例谢谢!
这里有几种可能的方法。
首先,readOnly
永远不会导致 JSON 架构的验证过程失败。这不是一个断言,只是一个注解,应用程序可以根据需要使用它来采取行动。因此,您的服务器应用程序可以随心所欲地处理它 - 如果有人试图更改它,则会引发错误,或者只是默默地忽略新值。
或者查看 HTTP Prefer
header,如果存在 handling=lenient
,请忽略任何更改 read-only 值的尝试,但如果存在 handling=strict
存在,任何尝试都会出错。
或者以不同的方式处理不同的字段。如果你有一个 lastModified
字段并支持 HTTP GET => modify => HTTP PUT 工作流,那么当你 PUT 一个表示时, lastModified
将不可避免地出错但 read-only 在某些时候.您不想因为过时的 auto-generated 时间戳而中断 PUT。但是如果有人认为他们可以更改 id
字段,您可能确实想提出错误。
鉴于此,有两种通用方法:编写一个双向工作的模式并在您的应用程序层中进行额外检查,或者分别确定输入和输出的所有内容。
"works both ways" 方法会从 required
中删除 id
,但请注意,一旦创建,资源将始终具有 id
。但是这样它可以在创建或写入时被省略而不会出现问题。要确定这是否合理,请考虑 client-side 输出验证的用例。客户端是否真的需要 JSON 架构来检查服务器是否发送了 id
,或者客户端是否可以根据文档合理地假设服务器会正确执行?
对于 "lock down each way" 方法,您可以这样做:
{
"definitions": {
"common": {
"type": "object",
"properties": {
"id": {
"type": "number",
"readOnly": true
},
"title": {
"type": "string"
},
"post": {
"type": "string"
}
},
"required": ["title", "post"],
"additionalProperties": false
},
"input": {
"allOf": [
{"$ref": "#/definitions/common"},
{"properties": {"id": false}}
]
},
"output": {
"allOf": [
{"$ref": "#/definitions/common"},
{"required": ["id"]}
]
}
}
}
您需要在公共模式中定义 id
以便 "additionalProperties": false
知道它(我尽量避免 "additionalProperties": false
因为它使得以兼容的方式演化表示变得困难,但是如果你想使用它,这是让它工作的方法。
对于输出,只需要id
。
对于输入,使用{"properties": {"id": false}}
禁用id
。即使它是在 "common" 中定义的,false
布尔模式总是会导致 id
无法通过输入验证。
当然,您必须弄清楚您的应用程序如何知道要使用哪个模式,因为再次 readOnly
其自身永远不会导致验证失败。这是我更喜欢为读取和写入使用一个模式并让应用程序处理差异(并记录该处理如何工作)的原因之一。