json 复杂模式可重用定义,忽略嵌套属性中的 $ref 验证
json complex schema reusable definitions, $ref validations in nested properties ignored
尝试学习 JSON 模式,我有一个复杂的模式,它完全基于相对 URL 的。当嵌套属性调用另一个文件中定义的定义 属性 时,验证有时会被忽略。
我的目标是基本上做出可重用的定义并在全球范围内经常使用enums/consts/definitions
假设项目树是:
-------------------------------------------
| C:/project |
| `----main.json (file to be validated) |
| `----/schemas |
| `----base.json |
| `----datatypes.json |
| `----defs.json |
| `----frequent.json |
| `----/pii |
| `----jobs.json |
-------------------------------------------
根据我对 $id
如何在根级别 ref 工作的理解,它为模式设置了基础 uri,其中 $ref
是相对的。但是,在某些情况下,我的架构未针对错误值进行验证,而其他情况下。嵌套,否则。
datatypes.json
{
"$id": "http://project.com/schemas/datatypes.json",
"$schema" : "http://json-schema.org/draft-07/schema",
"definitions" : {
"type_number": {
"type": "number",
"default": 0.0
},
"type_integer": {
"type": "integer",
"default": 0
},
"type_nonempty_string" : {
"type": "string",
"minLength": 1,
"pattern": "^([^\s].*[^\s]*)$"
}
}
}
defs.json
{
"$id": "http://project.com/schemas/defs.json",
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {
"number": {
"$ref": "./datatypes.json#/definitions/type_number"
},
"null_number": {
"oneOf": [
{
"$ref": "#/definitions/number"
},
{
"type": "null"
}
]
},
"positive_number": {
"$ref": "#/definitions/number",
"minimum": 0.0
},
"positive_nonzero_number": {
"$ref": "#/definitions/number",
"exclusiveMinimum": 0.0
},
"integer": {"$ref": "./datatypes.json#/definitions/type_integer"},
"positive_integer" : {
"$ref": "#/definitions/integer",
"minimum" : 0
},
"positive_nonzero_integer" : {
"$ref": "#/definitions/integer",
"exclusiveMinimum" : 0
},
"strict_object": {
"type": "object",
"additionalProperties": false
},
"nonempty_string": {"$ref": "./datatypes.json#/definitions/type_nonempty_string"},
"nonempty_string_null" : {
"oneOf": [
{
"$ref": "#/definitions/nonempty_string"
},
{
"type": "null"
}
]
}
}
}
frequent.json
{
"$id": "http://project.com/schemas/frequent.json",
"$schema" : "http://json-schema.org/draft-07/schema",
"definitions" : {
"SEX_TYPES" : {
"enum" : ["Male", "M","Female","F"]
},
"STATES" : {
"$comment" : "assume this is an emum of states in US",
"enum" : ["AK","AL","CT"]
},
"address" : {
"$ref" : "./defs.json#/definitions/strict_object",
"required" : ["street1", "city", "state", "zipcode"],
"properties" : {
"street1" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
"street2" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
"city" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
"state" : { "$ref" : "#/definitions/STATES" },
"zipcode" : { "$ref" : "#/definitions/zipcode" }
}
},
"zipcode": {
"allOf": [
{
"$ref": "./defs.json#/definitions/nonempty_string"
},
{
"pattern": "^(\d{5})$"
},
{
"not": {
"pattern": "^(00000)$"
}
}
]
}
}
}
base.json
{
"$id": "http://project.com/schemas/base.json",
"$schema" : "http://json-schema.org/draft-07/schema",
"type": "object",
"$ref": "./defs.json#/definitions/strict_object",
"properties": {
"main": {
"$ref": "./defs.json#/definitions/strict_object",
"required": ["age", "sex", "empl_num", "description", "address", "jobs"],
"properties": {
"age": {"$ref": "./defs.json#/definitions/positive_nonzero_integer"},
"sex": {"$ref": "./frequent.json#/definitions/SEX_TYPES" },
"empl_num" : {"$ref": "./defs.json#/definitions/positive_nonzero_integer"},
"description": {"$ref": "./defs.json#/definitions/nonempty_string"},
"jobs" : {"$ref": "pii/jobs.json"},
"address": {"$ref": "./frequent.json#/definitions/address"}
}
}
}
}
pii/jobs.json
{
"$id" : "http://project.com/schemas/pii/jobs.json",
"$schema": "http://json-schema.org/draft-07/schema",
"type" : "array",
"minItems": 1,
"items": {
"$ref" : "../defs.json#/definitions/strict_object",
"required": ["description","company","pay_details"],
"properties" : {
"description" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
"company" : {
"$ref": "../defs.json#/definitions/strict_object",
"required": ["name","address"],
"properties": {
"name" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
"address" : {"$ref": "../frequent.json#/definitions/address"}
}
},
"pay_details" : {
"$ref" : "../defs.json#/definitions/strict_object",
"required": ["pay_grade", "salary", "performance_review"],
"properties": {
"pay_grade" : { "$ref" : "../defs.json#/definitions/positive_nonzero_integer" },
"salary" : { "$ref" : "../defs.json#/definitions/positive_nonzero_number" },
"performance_review" : {
"$ref" : "../defs.json#/definitions/strict_object",
"required" : ["previous", "nextDate", "numberOfWriteUps"],
"properties" : {
"notes" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
"numberOfWriteUps" : {"$ref" : "../defs.json#/definitions/positive_integer" },
"previous" : {
"$ref" : "../defs.json#/definitions/strict_object",
"required": ["date", "rating"],
"properties": {
"date" : {
"$ref" : "../defs.json#/definitions/nonempty_string",
"format" : "date-time"
},
"rating" : {"$ref" : "../defs.json#/definitions/positive_integer" }
}
},
"nextDate" : {
"$ref" : "../defs.json#/definitions/nonempty_string",
"format" : "date-time"
}
}
}
}
}
}
}
}
在 intellij 中,结果如下:(显示的每个 属性 都不应该是有效的,但是有些只是被忽略和允许(如负数和空值等)。我没有得到 warnings/errors 关于 $ref 无法解析。自动完成甚至为我完成相对文件名和定义 属性。
编辑
在进一步研究之后,我发现它与相对的 URL 相关。例如,在我的 pii(个人身份信息)文件夹中,作业模式所在的位置,如果我将该模式与其他模式一起移动到根目录,则所有内容都会得到正确验证。为了说明新的项目树:
-------------------------------------------
| C:/project |
| `----main.json (file to be validated) |
| `----/schemas |
| `----base.json |
| `----datatypes.json |
| `----defs.json |
| `----frequent.json |
| `----jobs.json |
-------------------------------------------
为简洁起见,我的架构实际上并未存储在 http://project.com
。根据我对 $id
的理解,这并不重要,它只是模式相互通信的一种方式。我想尽可能地模块化并将模式隔离到它们自己的子文件夹中(如 pii),但是在我的示例中它不会以这种方式验证。
看起来您的方向是正确的,但是您不能将 $ref
与同一对象中的其他关键字一起使用,因为在将 $ref
与 draft-7 [= 一起使用时它们总是被忽略22=] 架构。
8.3. Schema References With "$ref"
The "$ref" keyword is used to reference a schema, and provides the
ability to validate recursive structures through self-reference.
An object schema with a "$ref" property MUST be interpreted as a
"$ref" reference. The value of the "$ref" property MUST be a URI
Reference. Resolved against the current URI base, it identifies the
URI of a schema to use. All other properties in a "$ref" object MUST
be ignored.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-01#section-8.3
如果您想在同一模式对象中将 $ref
与其他关键字一起使用,则需要创建两个模式对象并将它们包装在 allOf
.
中
尝试学习 JSON 模式,我有一个复杂的模式,它完全基于相对 URL 的。当嵌套属性调用另一个文件中定义的定义 属性 时,验证有时会被忽略。
我的目标是基本上做出可重用的定义并在全球范围内经常使用enums/consts/definitions
假设项目树是:
-------------------------------------------
| C:/project |
| `----main.json (file to be validated) |
| `----/schemas |
| `----base.json |
| `----datatypes.json |
| `----defs.json |
| `----frequent.json |
| `----/pii |
| `----jobs.json |
-------------------------------------------
根据我对 $id
如何在根级别 ref 工作的理解,它为模式设置了基础 uri,其中 $ref
是相对的。但是,在某些情况下,我的架构未针对错误值进行验证,而其他情况下。嵌套,否则。
datatypes.json
{
"$id": "http://project.com/schemas/datatypes.json",
"$schema" : "http://json-schema.org/draft-07/schema",
"definitions" : {
"type_number": {
"type": "number",
"default": 0.0
},
"type_integer": {
"type": "integer",
"default": 0
},
"type_nonempty_string" : {
"type": "string",
"minLength": 1,
"pattern": "^([^\s].*[^\s]*)$"
}
}
}
defs.json
{
"$id": "http://project.com/schemas/defs.json",
"$schema": "http://json-schema.org/draft-07/schema",
"definitions": {
"number": {
"$ref": "./datatypes.json#/definitions/type_number"
},
"null_number": {
"oneOf": [
{
"$ref": "#/definitions/number"
},
{
"type": "null"
}
]
},
"positive_number": {
"$ref": "#/definitions/number",
"minimum": 0.0
},
"positive_nonzero_number": {
"$ref": "#/definitions/number",
"exclusiveMinimum": 0.0
},
"integer": {"$ref": "./datatypes.json#/definitions/type_integer"},
"positive_integer" : {
"$ref": "#/definitions/integer",
"minimum" : 0
},
"positive_nonzero_integer" : {
"$ref": "#/definitions/integer",
"exclusiveMinimum" : 0
},
"strict_object": {
"type": "object",
"additionalProperties": false
},
"nonempty_string": {"$ref": "./datatypes.json#/definitions/type_nonempty_string"},
"nonempty_string_null" : {
"oneOf": [
{
"$ref": "#/definitions/nonempty_string"
},
{
"type": "null"
}
]
}
}
}
frequent.json
{
"$id": "http://project.com/schemas/frequent.json",
"$schema" : "http://json-schema.org/draft-07/schema",
"definitions" : {
"SEX_TYPES" : {
"enum" : ["Male", "M","Female","F"]
},
"STATES" : {
"$comment" : "assume this is an emum of states in US",
"enum" : ["AK","AL","CT"]
},
"address" : {
"$ref" : "./defs.json#/definitions/strict_object",
"required" : ["street1", "city", "state", "zipcode"],
"properties" : {
"street1" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
"street2" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
"city" : { "$ref" : "./defs.json#/definitions/nonempty_string" },
"state" : { "$ref" : "#/definitions/STATES" },
"zipcode" : { "$ref" : "#/definitions/zipcode" }
}
},
"zipcode": {
"allOf": [
{
"$ref": "./defs.json#/definitions/nonempty_string"
},
{
"pattern": "^(\d{5})$"
},
{
"not": {
"pattern": "^(00000)$"
}
}
]
}
}
}
base.json
{
"$id": "http://project.com/schemas/base.json",
"$schema" : "http://json-schema.org/draft-07/schema",
"type": "object",
"$ref": "./defs.json#/definitions/strict_object",
"properties": {
"main": {
"$ref": "./defs.json#/definitions/strict_object",
"required": ["age", "sex", "empl_num", "description", "address", "jobs"],
"properties": {
"age": {"$ref": "./defs.json#/definitions/positive_nonzero_integer"},
"sex": {"$ref": "./frequent.json#/definitions/SEX_TYPES" },
"empl_num" : {"$ref": "./defs.json#/definitions/positive_nonzero_integer"},
"description": {"$ref": "./defs.json#/definitions/nonempty_string"},
"jobs" : {"$ref": "pii/jobs.json"},
"address": {"$ref": "./frequent.json#/definitions/address"}
}
}
}
}
pii/jobs.json
{
"$id" : "http://project.com/schemas/pii/jobs.json",
"$schema": "http://json-schema.org/draft-07/schema",
"type" : "array",
"minItems": 1,
"items": {
"$ref" : "../defs.json#/definitions/strict_object",
"required": ["description","company","pay_details"],
"properties" : {
"description" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
"company" : {
"$ref": "../defs.json#/definitions/strict_object",
"required": ["name","address"],
"properties": {
"name" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
"address" : {"$ref": "../frequent.json#/definitions/address"}
}
},
"pay_details" : {
"$ref" : "../defs.json#/definitions/strict_object",
"required": ["pay_grade", "salary", "performance_review"],
"properties": {
"pay_grade" : { "$ref" : "../defs.json#/definitions/positive_nonzero_integer" },
"salary" : { "$ref" : "../defs.json#/definitions/positive_nonzero_number" },
"performance_review" : {
"$ref" : "../defs.json#/definitions/strict_object",
"required" : ["previous", "nextDate", "numberOfWriteUps"],
"properties" : {
"notes" : { "$ref" : "../defs.json#/definitions/nonempty_string" },
"numberOfWriteUps" : {"$ref" : "../defs.json#/definitions/positive_integer" },
"previous" : {
"$ref" : "../defs.json#/definitions/strict_object",
"required": ["date", "rating"],
"properties": {
"date" : {
"$ref" : "../defs.json#/definitions/nonempty_string",
"format" : "date-time"
},
"rating" : {"$ref" : "../defs.json#/definitions/positive_integer" }
}
},
"nextDate" : {
"$ref" : "../defs.json#/definitions/nonempty_string",
"format" : "date-time"
}
}
}
}
}
}
}
}
在 intellij 中,结果如下:(显示的每个 属性 都不应该是有效的,但是有些只是被忽略和允许(如负数和空值等)。我没有得到 warnings/errors 关于 $ref 无法解析。自动完成甚至为我完成相对文件名和定义 属性。
编辑
在进一步研究之后,我发现它与相对的 URL 相关。例如,在我的 pii(个人身份信息)文件夹中,作业模式所在的位置,如果我将该模式与其他模式一起移动到根目录,则所有内容都会得到正确验证。为了说明新的项目树:
-------------------------------------------
| C:/project |
| `----main.json (file to be validated) |
| `----/schemas |
| `----base.json |
| `----datatypes.json |
| `----defs.json |
| `----frequent.json |
| `----jobs.json |
-------------------------------------------
为简洁起见,我的架构实际上并未存储在 http://project.com
。根据我对 $id
的理解,这并不重要,它只是模式相互通信的一种方式。我想尽可能地模块化并将模式隔离到它们自己的子文件夹中(如 pii),但是在我的示例中它不会以这种方式验证。
看起来您的方向是正确的,但是您不能将 $ref
与同一对象中的其他关键字一起使用,因为在将 $ref
与 draft-7 [= 一起使用时它们总是被忽略22=] 架构。
8.3. Schema References With "$ref"
The "$ref" keyword is used to reference a schema, and provides the ability to validate recursive structures through self-reference.
An object schema with a "$ref" property MUST be interpreted as a
"$ref" reference. The value of the "$ref" property MUST be a URI
Reference. Resolved against the current URI base, it identifies the
URI of a schema to use. All other properties in a "$ref" object MUST be ignored.
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-01#section-8.3
如果您想在同一模式对象中将 $ref
与其他关键字一起使用,则需要创建两个模式对象并将它们包装在 allOf
.