JSON-schema oneOf for option under root area
JSON-Schema oneOf for option under root area
我正在尝试让 "oneof" 允许在根项中使用选项,但找不到示例,我尝试的操作给出了错误。
如果它在另一个项目下但不在根 {'s
下,我可以让它工作
示例 - 具有必填字段(jobNum、payee、amount、type,)和付款类型选项(checkInfo 或 dollarAmt)的工作付款。我知道这可以通过其他方式完成,但我需要这种方法来处理更复杂的架构。
{
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
{
"JobNum": "x216",
"Payee": "John Doe",
"type" : "Cash",
"amount" : "112.25",
"cashInfo" : {
"dollarAmt" : "112",
"coinAmt" : "0.25"
}
}
以下给出了这个错误 - "Unexpected token encountered when reading value for 'oneOf'. Expected StartObject, Boolean, got StartArray"
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
]
},
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"number": "string"
}
},
"required": [ "checkInfo" ],
"additionalProperties": false
},
"ptCheck": {
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": [ "dollarAmt", "coinAmt" ],
"additionalProperties": false
}
},
"additionalProperties": false
}
oneOf
应该放在prope
- 必须使用
type: object
为 ptCash
和 ptCheck
重写规则
以下架构应与 ptCheck
一起使用:
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"type": "object",
"required": ["number"],
"properties": {
"number": {
"type": "string"
}
}
}
},
"required": [ "checkInfo" ]
},
"ptCheck": {
"properties": {
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": ["dollarAmt", "coinAmt"]
}
},
"required": ["cashInfo"]
}
}
}
举个例子如下:
import jsonschema
import simplejson as json
schema_filename = '47926398.json'
with open(schema_filename, 'r') as f:
schema_data = f.read()
schema = json.loads(schema_data)
# validate with checkInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# invalidate
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfox": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# validate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfox": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo.dollarAmtx
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmtx": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
您的架构存在一些问题。我在下面为您修复了它。我不会解释我所做的所有更改,因为我认为通过阅读架构,大部分内容都非常清楚。如果您想了解更多详细信息,请直接提问,我会用更多详细信息更新答案。
oneOf
关键字只能出现在架构中。 properties
关键字是一个对象,其值是模式。当您将 "oneOf" 直接放在 properties
下时,它不会被解释为关键字,而是被解释为名为 "oneOf" 的 属性。然后验证器会抱怨,因为 属性 "oneOf" 的值应该是一个模式,而不是像 oneOf
关键字那样的模式数组。
您对 additionalProperties
的使用无效。这个关键字并不像人们通常认为的那样起作用。 JSON 模式关键字不知道它们所在模式之外的任何状态。让我们先看看 oneOf
的 "ptCheck" 分支。这描述了 属性 "number",表示它是必需的,并且可能没有 "number" 以外的关键字。然后您的顶层定义属性 "jobNum"、"payee"、"amount" 和 "type",需要所有属性并且不允许其他属性。这两件事永远不可能同时成立。即使您的架构有效,也没有 JSON 值可以针对此架构有效。这就是为什么我将 "checkInfo" 和 "cashInfo" 的定义移到了顶层,只将 required
部分放在 oneOf
中。这种方法的唯一缺点是您可以同时传递 "checkInfo" 和 "cachInfo" 对象,它会进行验证。无关的 属性 被忽略。有很多解决方法,但它们问题重重,我不建议使用它们。
我总是建议人们不要使用 "additionalProperties": false
而是忽略未知属性。原因是 JSON Schema 是一个约束系统。任何有效的 JSON 都对空模式 ({}
) 有效,并且模式中的每个关键字都会添加一些约束。这与人们在定义 classes 时习惯使用的方法不同。空 class 不描述任何内容并添加有效值。我们使用 "additionalProperties": false
让 JSON Schema 的行为更像定义 class,但试图让 JSON Schema 表现得像它不是的东西会导致像那个那样的挑战你看这里
{
"description": "Job Payment",
"type": "object",
"required": ["jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": { "type": "string" },
"payee": { "type": "string" },
"amount": { "type": "string" },
"type": { "enum": ["check", "cash"] },
"checkInfo": {
"type": "object",
"properties": {
"number": { "type": "string" }
},
"required": ["number"]
},
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": { "type": "string" },
"coinAmt": { "type": "string" }
},
"required": ["dollarAmt", "coinAmt"]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCheck": {
"type": "object",
"properties": {
"type": { "enum": ["check"] }
},
"required": ["checkInfo"]
},
"ptCash": {
"type": "object",
"properties": {
"type": { "enum": ["cash"] }
},
"required": ["cashInfo"]
}
},
"additionalProperties": false
}
我正在尝试让 "oneof" 允许在根项中使用选项,但找不到示例,我尝试的操作给出了错误。 如果它在另一个项目下但不在根 {'s
下,我可以让它工作示例 - 具有必填字段(jobNum、payee、amount、type,)和付款类型选项(checkInfo 或 dollarAmt)的工作付款。我知道这可以通过其他方式完成,但我需要这种方法来处理更复杂的架构。
{
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
{
"JobNum": "x216",
"Payee": "John Doe",
"type" : "Cash",
"amount" : "112.25",
"cashInfo" : {
"dollarAmt" : "112",
"coinAmt" : "0.25"
}
}
以下给出了这个错误 - "Unexpected token encountered when reading value for 'oneOf'. Expected StartObject, Boolean, got StartArray"
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
]
},
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"number": "string"
}
},
"required": [ "checkInfo" ],
"additionalProperties": false
},
"ptCheck": {
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": [ "dollarAmt", "coinAmt" ],
"additionalProperties": false
}
},
"additionalProperties": false
}
oneOf
应该放在prope- 必须使用
type: object
为
ptCash
和 ptCheck
重写规则
以下架构应与 ptCheck
一起使用:
{
"description": "Job Payment",
"type": "object",
"required": [ "jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": {
"type": "string"
},
"payee": {
"type": "string"
},
"amount": {
"type": "string"
},
"type": {"enum": [ "check", "cash" ]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCash": {
"properties": {
"checkInfo": {
"type": "object",
"required": ["number"],
"properties": {
"number": {
"type": "string"
}
}
}
},
"required": [ "checkInfo" ]
},
"ptCheck": {
"properties": {
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": {
"type": "string"
},
"coinAmt": {
"type": "string"
}
},
"required": ["dollarAmt", "coinAmt"]
}
},
"required": ["cashInfo"]
}
}
}
举个例子如下:
import jsonschema
import simplejson as json
schema_filename = '47926398.json'
with open(schema_filename, 'r') as f:
schema_data = f.read()
schema = json.loads(schema_data)
# validate with checkInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfo": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# invalidate
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"checkInfox": {
"number": "386"
}
}
jsonschema.validate(json_obj, schema)
# validate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfox": {
"dollarAmt": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
# invalidate with cashInfo.dollarAmtx
json_obj = {
"jobNum": "x216",
"payee": "John Doe",
"type": "check",
"amount": "112.25",
"cashInfo": {
"dollarAmtx": "400",
"coinAmt": "30"
}
}
jsonschema.validate(json_obj, schema)
您的架构存在一些问题。我在下面为您修复了它。我不会解释我所做的所有更改,因为我认为通过阅读架构,大部分内容都非常清楚。如果您想了解更多详细信息,请直接提问,我会用更多详细信息更新答案。
oneOf
关键字只能出现在架构中。 properties
关键字是一个对象,其值是模式。当您将 "oneOf" 直接放在 properties
下时,它不会被解释为关键字,而是被解释为名为 "oneOf" 的 属性。然后验证器会抱怨,因为 属性 "oneOf" 的值应该是一个模式,而不是像 oneOf
关键字那样的模式数组。
您对 additionalProperties
的使用无效。这个关键字并不像人们通常认为的那样起作用。 JSON 模式关键字不知道它们所在模式之外的任何状态。让我们先看看 oneOf
的 "ptCheck" 分支。这描述了 属性 "number",表示它是必需的,并且可能没有 "number" 以外的关键字。然后您的顶层定义属性 "jobNum"、"payee"、"amount" 和 "type",需要所有属性并且不允许其他属性。这两件事永远不可能同时成立。即使您的架构有效,也没有 JSON 值可以针对此架构有效。这就是为什么我将 "checkInfo" 和 "cashInfo" 的定义移到了顶层,只将 required
部分放在 oneOf
中。这种方法的唯一缺点是您可以同时传递 "checkInfo" 和 "cachInfo" 对象,它会进行验证。无关的 属性 被忽略。有很多解决方法,但它们问题重重,我不建议使用它们。
我总是建议人们不要使用 "additionalProperties": false
而是忽略未知属性。原因是 JSON Schema 是一个约束系统。任何有效的 JSON 都对空模式 ({}
) 有效,并且模式中的每个关键字都会添加一些约束。这与人们在定义 classes 时习惯使用的方法不同。空 class 不描述任何内容并添加有效值。我们使用 "additionalProperties": false
让 JSON Schema 的行为更像定义 class,但试图让 JSON Schema 表现得像它不是的东西会导致像那个那样的挑战你看这里
{
"description": "Job Payment",
"type": "object",
"required": ["jobNum", "payee", "amount", "type"],
"properties": {
"jobNum": { "type": "string" },
"payee": { "type": "string" },
"amount": { "type": "string" },
"type": { "enum": ["check", "cash"] },
"checkInfo": {
"type": "object",
"properties": {
"number": { "type": "string" }
},
"required": ["number"]
},
"cashInfo": {
"type": "object",
"properties": {
"dollarAmt": { "type": "string" },
"coinAmt": { "type": "string" }
},
"required": ["dollarAmt", "coinAmt"]
}
},
"oneOf": [
{ "$ref": "#/definitions/ptCash" },
{ "$ref": "#/definitions/ptCheck" }
],
"definitions": {
"ptCheck": {
"type": "object",
"properties": {
"type": { "enum": ["check"] }
},
"required": ["checkInfo"]
},
"ptCash": {
"type": "object",
"properties": {
"type": { "enum": ["cash"] }
},
"required": ["cashInfo"]
}
},
"additionalProperties": false
}