在基于另一个架构对象的json架构上使用条件语句 [英] Use conditional statements on json schema based on another schema object
问题描述
我有一个像这样的json对象:
I have a json object like:
{
"session": {
"session_id": "A",
"start_timestamp": 1535619633301
},
"sdk": {
"name": "android",
"version": "21"
}
}
sdk name
可以是android or ios
.并且session_id
基于sdk json
中的name field
.我使用条件语句(使用草案7)编写了json schema
,如下所示:
The sdk name
can either be android or ios
. And the session_id
is based on name field
in sdk json
. I have written a json schema
using conditional statement (Using draft 7) as follows:
但是它以一种意想不到的方式工作:
But it works in an unexpected manner:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$ref": "#/definitions/Base",
"definitions": {
"Base": {
"type": "object",
"additionalProperties": false,
"properties": {
"session": {
"$ref": "#/definitions/Session"
},
"sdk": {
"$ref": "#/definitions/SDK"
}
},
"title": "Base"
},
"Session": {
"type": "object",
"additionalProperties": false,
"properties": {
"start_timestamp": {
"type": "integer",
"minimum": 0
},
"session_id": {
"type": "string",
"if": {
"SDK": {
"properties": {
"name": {
"enum": "ios"
}
}
}
},
"then": {
"pattern": "A"
},
"else": {
"pattern": "B"
}
}
},
"required": [
"session_id",
"start_timestamp"
],
"title": "Session"
},
"SDK": {
"type": "object",
"additionalProperties": false,
"properties": {
"version": {
"type": "string"
},
"name": {
"type": "string",
"enum": [
"ios",
"android"
]
}
},
"required": [
"name",
"version"
],
"title": "SDK"
}
}
}
因此,以下JSON通过:
So the following JSON Passes:
{
"session": {
"session_id": "A",
"start_timestamp": 1535619633301
},
"sdk": {
"name": "ios",
"version": "21"
}
}
但这失败了:
{
"session": {
"session_id": "B",
"start_timestamp": 1535619633301
},
"sdk": {
"name": "android",
"version": "21"
}
}
有人可以解释y吗?.即使通过了:
can someone explain y?.. Even this passes:
{
"session": {
"session_id": "A",
"start_timestamp": 1535619633301
},
"sdk": {
"name": "android",
"version": "21"
}
}
推荐答案
我认为您遇到的问题与此问题类似.
I think you're having a similar problem as in this question.
@Relequestual是正确的,因为您需要在SDK
标注周围使用properties
关键字.但是对于您想做的事情,您需要进行重组.
@Relequestual is right in that you need the properties
keyword around your SDK
callout. But for what you want to do, you need to reorganize.
子计划仅在实例级别运行,而不是在根级别运行.
Subschemas only operate on their level in the instance, not at the root.
将此模式考虑为包含one
和two
属性的简单JSON对象实例:
Consider this schema for a simple JSON object instance containing a one
and a two
property:
{
"properties": {
"one": {
"enum": ["yes", "no", "maybe"]
},
"two": {
"if": {
"properties": {
"one": {"const": "yes"}
}
},
"then": {
... // do some assertions on the two property here
},
"else": {
...
}
}
}
}
two
属性下的if
关键字只能考虑two
属性下的实例部分(即two
的值).它没有查看实例的根,因此根本看不到one
属性.
The if
keyword under the two
property can only consider the portion of the instance under the two
property (i.e. two
's value). It's not looking at the root of the instance, so it can't see the one
property at all.
要使其生效,以便two
属性子模式下的子模式可以在实例中看到one
属性,您必须将if
移到properties
关键字之外.
To make it so that the subschema under the two
property subschema can see the one
property in the instance, you have to move the if
outside of the properties
keyword.
{
"if": {
"properties": {
"one": {"const" : "yes"}
}
},
"then": {
... // do some assertions on the two property here
},
"else": {
... // assert two here, or have another if/then/else structure to test the one property some more
}
}
对于one
的两个可能值,这非常好.甚至三个可能的值也不错.但是,随着one
可能值的增加,if
的嵌套也会增加,这会使您的架构难以阅读(并可能使验证速度变慢).
For two possible values of one
, this is pretty good. Even three possible values isn't bad. However, as the possible values of one
increases, so does the nesting of if
s, which can make your schema horrible to read (and possibly make validation slower).
我建议使用anyOf
或oneOf
,而不是使用if
/then
/else
构造,其中每个子模式都代表实例的有效状态,并给出one
的不同值
Instead of using the if
/then
/else
construct, I suggest using an anyOf
or oneOf
where each subschema represents a valid state for the instance, given the varying values of one
.
{
"oneOf": [
{
"properties": {
"one": {"const": "yes"},
"two": ... // do some assertions on the two property here
}
},
{
"properties": {
"one": {"const": "no"},
"two": ... // do some assertions on the two property here
}
},
{
"properties": {
"one": {"const": "maybe"},
"two": ... // do some assertions on the two property here
}
}
]
}
我认为这要干净得多.
希望这种解释有助于您重构架构,以允许其他实例通过.
Hopefully that explanation helps you reconstruct your schema to allow those other instances to pass.
这篇关于在基于另一个架构对象的json架构上使用条件语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!