Newtonsoft.Json.Schema 未根据 JSON 模式正确验证 JSON 输入
Newtonsoft.Json.Schema is not validating JSON input correctly against a JSON schema
在下面的示例中,架构验证为以下负载 JSON 返回 true
,即使:
- "family_name" 和 "given_name" 是“名称”属性 中的必填字段,但在负载 JSON.
中缺失
- "given_name" 应该是一个字符串数组,但在负载 JSON.
中是一个简单的字符串
为什么这些错误没有被捕获?
我们正在使用 Newtonsoft.Json.Schema 进行验证。
JSON 架构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"article_metadata": {
"description": "article metadata for descrepancy checks",
"type": "object",
"properties": {
"authors": {
"description": "authors details",
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"family_name": {
"type": "string"
},
"required": [
"family_name",
"given_name"
]
}
},
"required": [
"sequence_id",
"name"
]
}
}
}
}
}
}
}
}
有效载荷JSON:
{
"article_metadata": {
"authors": {
"list": [{
"sequence_id": "Au1",
"guid": "00208406-c337-4f58-9245-9455d8852a00",
"affiliation_id": "Aff1",
"name": {
"prefix": "Ms.",
"family_name": "Hole"
}
}, {
"sequence_id": "Au2",
"guid": "32b8a598-2fb5-42f1-ad0e-94ce2fc00a8f",
"affiliation_id": "Aff2",
"name": {
"prefix": "Mr.",
"given_name": "Anurag"
}
}
]
}
}
}
您的问题可以通过演示重现 fiddle #1 here.
让我们尝试将其分解为 Minimal, Reproducible Example。如果我们从整体模式中仅提取 "name"
个对象的模式,它看起来像:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"family_name": {
"type": "string"
},
"required": [
"family_name",
"given_name"
]
}
}
并且缺少所有必需属性的相应无效 JSON 对象如下所示:
{
"prefix": "Mr."
}
如果我尝试根据此架构验证 JSON,则无法解析架构本身,并引发以下错误:
Newtonsoft.Json.Schema.JSchemaReaderException: Unexpected token encountered when reading value for 'required'. Expected StartObject, Boolean, got StartArray. Path 'properties.required', line 18, position 53.
演示 fiddle #2 here.
这里的问题是您已将所需属性列表 添加为 属性 本身 。您需要从属性列表中提取所需的属性,如下所示:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"family_name": {
"type": "string"
}
},
"required": [
"family_name",
"given_name"
]
}
现在您的架构将成功加载并正确验证 "name"
对象,生成以下错误:
Required properties are missing from object: family_name, given_name. Path '', line 1, position 2.
演示 fiddle #3 here.
但是,您的原始 JSON 架构不会引发 JSchemaReaderException
错误,它只是无法正确验证。这是为什么?您用于 "list"
数组项的语法似乎是错误的——错误的程度足以使 Json.NET 模式解析器变得混乱。为此,您可以立即列出您希望在数组项中找到的 属性 值,如下所示:
{
"type": "array",
"items": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
// Contents omitted for brevity
},
"required": [
"sequence_id",
"name"
]
}
}
但是,如https://json-schema.org/understanding-json-schema/reference/array.html所示,数组项的定义方式与定义属性值或根对象的方式相同,特别是通过指示"type"
项目(此处 "object"
),然后给出特定于类型的约束。因此,您的模式的这一部分应该如下所示:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
// Contents omitted for brevity
}
},
"required": [
"sequence_id",
"name"
]
}
}
当我对您的架构进行此更正时,您的 JSON 现在可以正确验证,生成以下错误:
Required properties are missing from object: given_name. Path 'article_metadata.authors.list[0].name', line 8, position 29.
Invalid type. Expected Array but got String. Path 'article_metadata.authors.list[1].name.given_name', line 18, position 46.
Required properties are missing from object: family_name. Path 'article_metadata.authors.list[1].name', line 16, position 29.
您的最终架构应如下所示:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"article_metadata": {
"description": "article metadata for descrepancy checks",
"type": "object",
"properties": {
"authors": {
"description": "authors details",
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"type": "object",
"properties": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
"family_name": {
"type": "string"
}
},
"required": [
"family_name",
"given_name"
]
}
},
"required": [
"sequence_id",
"name"
]
}
}
}
}
}
}
}
}
演示 fiddle #4 here.
在下面的示例中,架构验证为以下负载 JSON 返回 true
,即使:
- "family_name" 和 "given_name" 是“名称”属性 中的必填字段,但在负载 JSON. 中缺失
- "given_name" 应该是一个字符串数组,但在负载 JSON. 中是一个简单的字符串
为什么这些错误没有被捕获?
我们正在使用 Newtonsoft.Json.Schema 进行验证。
JSON 架构:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"article_metadata": {
"description": "article metadata for descrepancy checks",
"type": "object",
"properties": {
"authors": {
"description": "authors details",
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"family_name": {
"type": "string"
},
"required": [
"family_name",
"given_name"
]
}
},
"required": [
"sequence_id",
"name"
]
}
}
}
}
}
}
}
}
有效载荷JSON:
{
"article_metadata": {
"authors": {
"list": [{
"sequence_id": "Au1",
"guid": "00208406-c337-4f58-9245-9455d8852a00",
"affiliation_id": "Aff1",
"name": {
"prefix": "Ms.",
"family_name": "Hole"
}
}, {
"sequence_id": "Au2",
"guid": "32b8a598-2fb5-42f1-ad0e-94ce2fc00a8f",
"affiliation_id": "Aff2",
"name": {
"prefix": "Mr.",
"given_name": "Anurag"
}
}
]
}
}
}
您的问题可以通过演示重现 fiddle #1 here.
让我们尝试将其分解为 Minimal, Reproducible Example。如果我们从整体模式中仅提取 "name"
个对象的模式,它看起来像:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"family_name": {
"type": "string"
},
"required": [
"family_name",
"given_name"
]
}
}
并且缺少所有必需属性的相应无效 JSON 对象如下所示:
{
"prefix": "Mr."
}
如果我尝试根据此架构验证 JSON,则无法解析架构本身,并引发以下错误:
Newtonsoft.Json.Schema.JSchemaReaderException: Unexpected token encountered when reading value for 'required'. Expected StartObject, Boolean, got StartArray. Path 'properties.required', line 18, position 53.
演示 fiddle #2 here.
这里的问题是您已将所需属性列表 添加为 属性 本身 。您需要从属性列表中提取所需的属性,如下所示:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"family_name": {
"type": "string"
}
},
"required": [
"family_name",
"given_name"
]
}
现在您的架构将成功加载并正确验证 "name"
对象,生成以下错误:
Required properties are missing from object: family_name, given_name. Path '', line 1, position 2.
演示 fiddle #3 here.
但是,您的原始 JSON 架构不会引发 JSchemaReaderException
错误,它只是无法正确验证。这是为什么?您用于 "list"
数组项的语法似乎是错误的——错误的程度足以使 Json.NET 模式解析器变得混乱。为此,您可以立即列出您希望在数组项中找到的 属性 值,如下所示:
{
"type": "array",
"items": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
// Contents omitted for brevity
},
"required": [
"sequence_id",
"name"
]
}
}
但是,如https://json-schema.org/understanding-json-schema/reference/array.html所示,数组项的定义方式与定义属性值或根对象的方式相同,特别是通过指示"type"
项目(此处 "object"
),然后给出特定于类型的约束。因此,您的模式的这一部分应该如下所示:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
// Contents omitted for brevity
}
},
"required": [
"sequence_id",
"name"
]
}
}
当我对您的架构进行此更正时,您的 JSON 现在可以正确验证,生成以下错误:
Required properties are missing from object: given_name. Path 'article_metadata.authors.list[0].name', line 8, position 29. Invalid type. Expected Array but got String. Path 'article_metadata.authors.list[1].name.given_name', line 18, position 46. Required properties are missing from object: family_name. Path 'article_metadata.authors.list[1].name', line 16, position 29.
您的最终架构应如下所示:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"article_metadata": {
"description": "article metadata for descrepancy checks",
"type": "object",
"properties": {
"authors": {
"description": "authors details",
"type": "object",
"properties": {
"list": {
"type": "array",
"items": {
"type": "object",
"properties": {
"sequence_id": {
"type": "string"
},
"guid": {
"description": "32 digit unique id to identify author",
"type": "string"
},
"name": {
"type": "object",
"properties": {
"prefix": {
"type": "string"
},
"given_name": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
"family_name": {
"type": "string"
}
},
"required": [
"family_name",
"given_name"
]
}
},
"required": [
"sequence_id",
"name"
]
}
}
}
}
}
}
}
}
演示 fiddle #4 here.