Reputation: 9086
I am trying to model the scenario where the JSON payload has a "steps" array and it's contents may be only one of predefined a set of options, for example:
{ "steps": ["s0"] }
or
{ "steps": ["s1"] }
or
{ "steps": ["s0", "s2"] }
How would I model this in a schema? The following:
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Payload",
"type": "object",
"properties": {
"steps": {
"type": "array",
"oneOf": [
["s0"],
["s1"],
["s0", "s2"]
]
}
}
}
fails with "Unexpected token when reading schemas: StartArray. Path 'properties.steps.oneOf[0]'"
EDIT
Apologies for moving the goalposts, I simplified my problem to a point where the proposed solutions work for the simplified
version but not the original. The extra complication is that instead of string
values I need to $ref
objects sooo...
Sample inputs:
{ "steps": [{"name": "S0"}] }
or
{ "steps": [{"name": "S1"}] }
or
{ "steps": [{"name": "S1"}, {"name": "S2"}] }
A schema (following suggestion by @EylM) that doesn't match as expected
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Request",
"type": "object",
"properties": {
"steps": {
"type": "array",
"oneOf": [
{
"const": [
{"$ref": "#/definitions/s0"}
]
},
{
"const": [
{"$ref": "#/definitions/s1"}
]
},
{
"const": [
{"$ref": "#/definitions/s1"},
{"$ref": "#/definitions/s2"}
]
}
]
}
},
"required": [
"steps"
],
"definitions": {
"s0": {
"type": "object",
"properties": {"name": { "const": "S0" }}
},
"s1": {
"type": "object",
"properties": {"name": {"const": "S1" }}
},
"s2": {
"type": "object",
"properties": {"name": { "const": "S2" }}
}
}
}
With this schema and input { "steps":[{"name": "s0"}] }
I get
JSON is valid against no schemas from 'oneOf'
For whatever it's worth, I am using https://www.jsonschemavalidator.net/ for experimenting.
Upvotes: 1
Views: 9879
Reputation: 443
Updated my answer according to your edit. Following JSON schema validates all 3 conditions in the question and I assumed { "steps": [{"name": "S2"}, {"name": "S1"}] }
is not valid. Correct me if I'm wrong.
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Request",
"type": "object",
"properties": {
"steps": {
"type": "array",
"anyOf": [
{
"maxItems": 1,
"items": {
"oneOf": [
{
"$ref": "#/definitions/s0"
},
{
"$ref": "#/definitions/s1"
}
]
}
},
{
"minItems": 2,
"maxItems": 2,
"items": [
{
"$ref": "#/definitions/s1"
},
{
"$ref": "#/definitions/s2"
}
]
}
]
}
},
"required": [
"steps"
],
"definitions": {
"s0": {
"type": "object",
"properties": {
"name": {
"const": "S0"
}
}
},
"s1": {
"type": "object",
"properties": {
"name": {
"const": "S1"
}
}
},
"s2": {
"type": "object",
"properties": {
"name": {
"const": "S2"
}
}
}
}
}
In case you want to pass validation for { "steps": [{"name": "S2"}, {"name": "S1"}] }
use another anyOf block as follows.
{
"minItems": 2,
"maxItems": 2,
"items": [
{
"$ref": "#/definitions/s2"
},
{
"$ref": "#/definitions/s1"
}
]
}
Upvotes: 1
Reputation: 6103
Try using enum keyword.
The
enum
keyword is used to restrict a value to a fixed set of values. It must be an array with at least one element, where each element is unique.
In your case, JSON would look like:
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Payload",
"type": "object",
"properties": {
"steps": {
"type": "array",
"oneOf": [
{"enum": ["s1"]},
{"enum": ["s0"]},
{"enum": ["s1, s2"]}
]
}
}
}
Upvotes: 2