我在提出JSON模式时遇到问题,该模式将验证JSON是否包含:
但是当它们的倍数存在时不匹配。
具体来说,我需要一个
copyAll
fileNames
matchesFiles
和/或doesntMatchFiles
要验证,但我不想接受超过那个时间。
这是我到目前为止所得到的:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [ "unrelatedA" ],
"properties": {
"unrelatedA": {
"type": "string"
},
"fileNames": {
"type": "array"
},
"copyAll": {
"type": "boolean"
},
"matchesFiles": {
"type": "array"
},
"doesntMatchFiles": {
"type": "array"
}
},
"oneOf": [
{"required": ["copyAll"], "not":{"required":["matchesFiles"]}, "not":{"required":["doesntMatchFiles"]}, "not":{"required":["fileNames"]}},
{"required": ["fileNames"], "not":{"required":["matchesFiles"]}, "not":{"required":["doesntMatchFiles"]}, "not":{"required":["copyAll"]}},
{"anyOf": [
{"required": ["matchesFiles"], "not":{"required":["copyAll"]}, "not":{"required":["fileNames"]}},
{"required": ["doesntMatchFiles"], "not":{"required":["copyAll"]}, "not":{"required":["fileNames"]}}]}
]
} ;
这比我想要的更多。我希望这匹配以下所有内容:
{"copyAll": true, "unrelatedA":"xxx"}
{"fileNames": ["aab", "cab"], "unrelatedA":"xxx"}
{"matchesFiles": ["a*"], "unrelatedA":"xxx"}
{"doesntMatchFiles": ["a*"], "unrelatedA":"xxx"}
{"matchesFiles": ["a*"], "doesntMatchFiles": ["*b"], "unrelatedA":"xxx"}
但不匹配:
{"copyAll": true, "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"fileNames": ["a"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"copyAll": true, "doesntMatchFiles": ["*b"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"fileNames": ["a"], "matchesFiles":["a*"], "unrelatedA":"xxx"}
{"unrelatedA":"xxx"}
我猜测那里有一些我不知道的东西 - 我想知道它是什么。
答案 0 :(得分:76)
问题是“不”语义。 “不要求”并不意味着“包容禁止”。它只是意味着您不必添加它以验证该架构。
但是,您可以使用“oneOf”以更简单的方式满足您的规范。请记住,这意味着“只需要其中一个模式可以验证”。以下模式实现了您尝试解决的属性切换:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": [
"unrelatedA"
],
"properties": {
"unrelatedA": {
"type": "string"
},
"fileNames": {
"type": "array"
},
"copyAll": {
"type": "boolean"
},
"matchesFiles": {
"type": "array"
},
"doesntMatchFiles": {
"type": "array"
}
},
"oneOf": [
{
"required": [
"copyAll"
]
},
{
"required": [
"fileNames"
]
},
{
"anyOf": [
{
"required": [
"matchesFiles"
]
},
{
"required": [
"doesntMatchFiles"
]
}
]
}
]
}
答案 1 :(得分:0)
此答案与JSON模式无关,因此虽然可以带来解决此问题的另一种观点,但通常还是可以进行json验证,所以它有点偏离轨道。
重点是确切地声明您需要的结果:一个唯一的字段。考虑以下json模式:
JsonElement json =
new Gson().toJsonTree(
Map.of(
"first_field", "vasya",
"second_field", false,
"third_field", 777,
"unrelated", "Rinse"
)
);
假设您需要first_field
,second_field
和third_field
中的任何一个。第四场无关紧要。这是相应的验证对象的样子:
Result<SomeTestStructure> result =
new UnnamedBlocOfNameds<SomeTestStructure>(
List.of(
new OneOf(
"global",
new ErrorStub("Only one of the fields must be present"),
new AsString(
new Required(
new IndexedValue("first_field", json)
)
),
new AsBoolean(
new Required(
new IndexedValue("second_field", json)
)
),
new AsInteger(
new Required(
new IndexedValue("third_field", json)
)
)
),
new AsString(
new IndexedValue("unrelated", json)
)
),
SomeTestStructure.class
)
.result();
首先,您声明一个由命名对象组成的未命名块;那么您说您需要三个元素中的一个成功的可验证元素。最后,您声明成功意味着什么。在这种情况下,成功就是简单存在。如果json有效,则创建SomeTestStructure
类的对象:
assertTrue(result.isSuccessful());
assertEquals(
new SomeTestStructure(777, "Rinse").thirdField(),
result.value().raw().thirdField()
);
有关此方法和实现该方法的库的更多信息,请查看quick start entry。
答案 2 :(得分:0)
如果值为 null
的属性与其不存在一样好,那么这样的事情可能是合适的。必须提供 commonProp
,并且只能提供 x
或 y
之一。
不过,您可能会收到一些类似的错误消息。
{
$schema: 'http://json-schema.org/draft-07/schema#',
type: 'object',
required: ['commonProp'],
oneOf: [
{
properties: {
x: { type: 'number' },
commonProp: { type: 'number' },
y: {
type: 'null',
errorMessage: "should ONLY include either ('x') or ('y') keys. Not a mix.",
},
},
additionalProperties: { not: true, errorMessage: 'remove additional property ${0#}' },
},
{
properties: {
y: { type: 'number' },
commonProp: { type: 'number' },
x: {
type: 'null',
errorMessage: "should ONLY include either ('x') or ('y') keys. Not a mix.",
},
},
additionalProperties: { not: true, errorMessage: 'remove additional property ${0#}' },
},
],
}
const model = { x: 0, y: 0, commonProp: 0 };
// ⛔️ ⛔️ ⛔️ ⛔️ ⛔️ ⛔️
// Model>y should ONLY include either ('x') or ('y') keys. Not a mix.
// Model>x should ONLY include either ('x') or ('y') keys. Not a mix.
const model = { x: 0, y: null, commonProp: 0 };
// ✅ ✅ ✅ ✅ ✅ ✅
const model = { x: 0 };
// ⛔️ ⛔️ ⛔️ ⛔️ ⛔️ ⛔️
// Model must have required property 'commonProp'