我正在尝试创建一个自定义 jsonschema 关键字来进行一些基本评估。一个例子是“parallelArrays”,其中将检查提供的列表以确保它们的长度相同。
我在很大程度上成功地做到了这一点,但我最近意识到我犯了一个错误。我想在架构中使用此关键字来表示我的实际数据。为了确保我正确使用关键字,我想根据元模式验证模式本身,这将确保(除其他外)“parallelArrays”关键字在模式中格式良好。
当我在架构的顶级对象中使用自定义关键字时,此元架构验证效果很好,但当我在其他地方(例如在嵌套对象中)使用它时,它会失败。
我在下面有一个示例,其中包含自定义关键字“myKeyword”,它不执行任何操作,但必须是一个对象。请注意,下面的示例使用 jschon python 库,但我在 python-jsonschema 中观察到了同样的问题。我假设我一开始形成词汇的方式有问题,但我无法弄清楚
假设以下文件位于同一文件夹中:
meta.schema.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/myKeyword/meta.schema.json",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/core": true,
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
"https://json-schema.org/draft/2020-12/vocab/validation": true,
"https://json-schema.org/draft/2020-12/vocab/meta-data": true,
"https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
"https://json-schema.org/draft/2020-12/vocab/content": true,
"https://json-schema.org/draft/2020-12/vocab/unevaluated": true
},
"allOf": [
{ "$ref": "https://json-schema.org/draft/2020-12/schema" },
{ "$ref": "https://example.com/myKeyword/vocab.schema.json" }
]
}
vocab.schema.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/myKeyword/meta.schema.json",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/core": true,
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
"https://json-schema.org/draft/2020-12/vocab/validation": true,
"https://json-schema.org/draft/2020-12/vocab/meta-data": true,
"https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
"https://json-schema.org/draft/2020-12/vocab/content": true,
"https://json-schema.org/draft/2020-12/vocab/unevaluated": true
},
"allOf": [
{ "$ref": "https://json-schema.org/draft/2020-12/schema" },
{ "$ref": "https://example.com/myKeyword/vocab.schema.json" }
]
}
test.py(您需要 pip install jschon)
import os
import jschon
# This just helps jschon locate our schema files
catalog = jschon.create_catalog("2020-12")
catalog.add_uri_source(jschon.URI("https://example.com/myKeyword/"), jschon.LocalSource(os.path.dirname(__file__)))
### Test 1 ###
# myKeyword is in the top level of the schema and is an object
user_schema = jschon.JSONSchema({
"$schema": "https://example.com/myKeyword/meta.schema.json",
"$id": "https://example.com/mySchema",
"type": "object",
"myKeyword": {},
"properties": {
"favoriteNumber": {
"type": "integer",
}
}
})
assert(user_schema.validate().valid is True) # Passes
### Test 2 ###
# myKeyword is in the top level of the schema and is NOT an object
user_schema = jschon.JSONSchema({
"$schema": "https://example.com/myKeyword/meta.schema.json",
"$id": "https://example.com/mySchema",
"type": "object",
"myKeyword": [],
"properties": {
"favoriteNumber": {
"type": "integer",
}
}
})
assert(user_schema.validate().valid is False) # Passes
### Test 3 ###
# myKeyword is NOT in the top level of the schema and is an object
user_schema = jschon.JSONSchema({
"$schema": "https://example.com/myKeyword/meta.schema.json",
"$id": "https://example.com/mySchema",
"type": "object",
"properties": {
"favoriteNumber": {
"type": "integer",
"myKeyword": {}
}
}
})
assert(user_schema.validate().valid is True) # Passes (but trivially, see below)
### Test 4 ###
# myKeyword is NOT in the top level of the schema and is NOT an object
user_schema = jschon.JSONSchema({
"$schema": "https://example.com/myKeyword/meta.schema.json",
"$id": "https://example.com/mySchema",
"type": "object",
"properties": {
"favoriteNumber": {
"type": "integer",
"myKeyword": []
}
}
})
assert(user_schema.validate().valid is False) # Fails!
# Essentially, when "myKeyword" is not in the top level, it is always marked as valid because
# for some reason the vocab.schema.json is not checked. This is why Test 3 passes but I called
# it trivial.
JSON 模式作者之一有一些关于这个主题的精彩博客文章。
https://blog.json-everything.net/posts/updating-vocabs/
https://docs.json-everything.net/schema/vocabs/data-2023/
查看您的架构,似乎您的词汇架构有很多不必要的定义
我相当确定这会让您到达您想要的位置。
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/myKeyword/vocab.schema.json",
"$defs": {
"myKeyword": {}
},
"title": "my keyword for parallel arrays",
"$ref": "#/$defs/myKeyword"
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schema/meta/myKeyword",
"$dynamicAnchor": "meta",
"$vocabulary": {
<All core vocabs>,
"https://example.com/meta/myKeyword/vocab.schema.json": true
},
"allOf": [
{"$ref": "https://json-schema.org/draft/2020-12/schema"},
{"$ref": "https://example.com/myKeyword/vocab.schema.json"}]
}