考虑一个带有端点的API,您可以在其中传递参数foo
作为URL路径的一部分,并将一些参数作为json传递给POST请求的主体。
foo
必须包含值fooBar
和fooBaz
之一。否则请求标记为404。foo
的值为fooBar
,则需要正文属性bar
。foo
的值为fooBaz
,则需要正文属性baz
。如何为这样的端点指定jsonSchema?
此类请求的示例如下:
POST /path/to/endpoint/fooBar HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 20
{"bar":"something"}
到目前为止,我基于this和that提出了以下内容,但我不知道这是否正确。
{
"$schema": "http://json-schema.org/draft-03/schema#",
"id": "http://json-schema.org/draft-03/schema#",
"definitions": {
"foo": { "enum": ["fooBar", "fooBaz"] }
},
"type": "object",
"properties": {
"foo": { "$ref": "#/definitions/foo" },
"bar": { "type": "string" },
"baz": { "type": "string" }
},
"links": [{
"rel": "self",
"href": "/path/to/endpoint/{foo}",
"hrefSchema": {
"properties": {
"foo": {"$ref": "#/definitions/foo"}
}
}
}],
"anyOf": [
{
"properties": {
"foo": { "enum": ["fooBar"] }
},
"required": ["bar"]
},
{
"properties": {
"foo": { "enum": ["fooBaz"] }
},
"required": ["baz"]
},
]
}
答案 0 :(得分:1)
JSON Schema验证不知道正在验证的数据来自的URI(如果有)。您可以使用JSON Hyper-Schema告诉用户如何以您期望的方式发送数据,但您仍需要在服务器端进行额外检查以验证请求是否已正确发送。
在我进入解决方案之前,我想指出一些事情。您的$schema
设置为" draft-03"。如果你真的需要" draft-03",这个解决方案不会起作用。在{" draft-04"中添加了anyOf
,allOf
和数组形式的required
。在{" draft-06"中添加了hrefSchema
。自" draft-06"是全新的,并没有得到很好的支持,无论如何你都不需要hrefSchema
,我会假设"选秀04" ("草案05"被有效跳过)。
接下来要提到的是你使用id
错误。它应该是您的架构的标识符。您通常不需要这个,但如果您这样做,它应该是标识您的架构的完整URI。这就是我的解决方案使用它的方式。
在我进入解决方案之前的最后一件事。如果您使用的是link
关键字,那么您使用的是JSON超模式,$schema
应该反映出来。它应该有"超模式"而不是"架构"在URI的末尾。
现在的解决方案。我把它分为两部分,你通过验证器发出的模式和告诉用户如何发出请求的超模式。你有第一个正确的。我只修复了$schema
和id
。
{
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "http://example.com/schema/my-foo-schema",
"type": "object",
"properties": {
"foo": { "enum": ["fooBar", "fooBaz"] },
"bar": { "type": "string" },
"baz": { "type": "string" }
},
"anyOf": [
{
"properties": {
"foo": { "enum": ["fooBar"] }
},
"required": ["bar"]
},
{
"properties": {
"foo": { "enum": ["fooBaz"] }
},
"required": ["baz"]
}
]
}
接下来是超架构。您无法在请求架构中引用任何外部(href,实例数据),但您可以编写架构以使其与href
匹配。重复是不幸的,但这就是你必须这样做的方式。
{
"$schema": "http://json-schema.org/draft-04/hyper-schema#",
"links": [
{
"rel": "http://example.com/rel/my-foo-relation",
"href": "/path/to/endpoint/fooBar",
"method": "POST",
"schema": {
"allOf": [{ "$ref": "http://example.com/schema/my-foo-schema" }],
"properties": {
"foo": { "enum": ["fooBar"] }
}
}
},
{
"rel": "http://example.com/rel/my-foo-relation",
"href": "/path/to/endpoint/fooBaz",
"method": "POST",
"schema": {
"allOf": [{ "$ref": "http://example.com/schema/my-foo-schema" }],
"properties": {
"foo": { "enum": ["fooBaz"] }
}
}
},
{
"rel": "self",
"href": "/path/to/endpoint"
}
]
}
通常当我遇到难以使用超级模式进行建模的事情时,这意味着我正在做一些过于复杂的API,我需要重构。我建议花几分钟时间考虑替代设计,因为这不需要对枚举进行切换。