I am having trouble coming up with a JSON schema that will validate if the JSON contains either:
This answer is not related to JSON schema, so it's a bit off the track, though it can bring another perspective on solving this problem, and json validation in general.
The point is to express declaratively exactly what you need as a result: a single field which is the only present. Consider the following json schema:
JsonElement json =
new Gson().toJsonTree(
Map.of(
"first_field", "vasya",
"second_field", false,
"third_field", 777,
"unrelated", "Rinse"
)
);
Let's say you need either one of the first_field
, second_field
, and third_field
. The fourth field doesn't matter. Here is how the corresponding validation object looks like:
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();
First, you declare an unnamed block consisting of named ones; then you say that you need a single successful validatable element out of the three ones. And finally, you declare what success means. In this case, to be successful is to be simply present. If json is valid, an object of SomeTestStructure
class is created:
assertTrue(result.isSuccessful());
assertEquals(
new SomeTestStructure(777, "Rinse").thirdField(),
result.value().raw().thirdField()
);
For more info about this approach and a library implementing it, check out a quick start entry.
The problem is the "not" semantics. "not required" does not mean "inclusion forbidden". It just means that you don't have to add it in order to validate that schema.
However, you can use "oneOf" to satisfy your specification in a simpler way. Remember that it means that "just one of these schemas can validate". The following schema achieves the property switching you are attempting to solve:
{
"$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"
]
}
]
}
]
}