1

I am trying to write a schema validating arrays with the following structural constraints:

  • it can only ever contain the values 1,2,3,4,5
  • if the array contains a 1, that must be the only entry
  • the array can only contain either 2, 3 or 4 at the same time, so e.g. [2,3] is not allowed
  • 5 can be present together with 2,3,4

so the valid arrays are

[1],
[2],
[3],
[4],
[5],
[2,5],
[3,5],
[4,5]

I started writing a schema as follows:

{
    "type": "array",
    "oneOf": [
        { "items": { "enum": [1] } },
        {
            "anyOf": [
                ???
            ]
        }
    ]
}

I can't get the ??? part to work. Is it possible at all? NOTE: I would like to avoid hardcoding all possible arrays, as I have to validate more complex structures - this is only an example. Also, the optimum is a solution using only anyOf, allOf, oneOf, not, avoiding keywords like minItems

1 Answer 1

1

This passes all of your constraints.

{
  "type": "array",
  "anyOf": [
    { "enum": [[1]] },
    {
      "items": { "enum": [2, 3, 4, 5] },
      "oneOf": [
        { "$ref": "#/definitions/doesnt-contain-2-3-or-4" },
        { "$ref": "#/definitions/contains-2" },
        { "$ref": "#/definitions/contains-3" },
        { "$ref": "#/definitions/contains-4" }
      ]
    }
  ],
  "definitions": {
    "doesnt-contain-2-3-or-4": {
      "items": { "not": { "enum": [2, 3, 4] } }
    },
    "contains-2": {
      "not": {
        "items": { "not": { "enum": [2] } }
      }
    },
    "contains-3": {
      "not": {
        "items": { "not": { "enum": [3] } }
      }
    },
    "contains-4": {
      "not": {
        "items": { "not": { "enum": [4] } }
      }
    }
  }
}

If you have the option of using the new draft-06 keywords contains and const, it's actually a pretty clean solution. There is a little duplication, but I don't think that can be helped.

{
  "type": "array",
  "anyOf": [
    { "const": [1] },
    {
      "items": { "enum": [2, 3, 4, 5] },
      "oneOf": [
        { "not": { "contains": { "enum": [2 ,3, 4] } } },
        { "contains": { "const": 2 } },
        { "contains": { "const": 3 } },
        { "contains": { "const": 4 } }
      ]
    }
  ]
}
Sign up to request clarification or add additional context in comments.

4 Comments

@tscherg It's an enum that contains a single value and that value is [1]. It's the simplest way to say that 1 must stand alone. This works because enum is not limited to simple types.
I'll accept your answer, thanks again. I've had a quick look around and there seem to be no v6 validators for PHP around yet. Did you come across one?
@tscherg The only validator I've seen in any language that supports draft-06 is ajv, but that's for JavaScript. Hopefully there is someone out there working on one for PHP
I know that the folks over at github.com/justinrainbow/json-schema are currently reviewing the PR for v6 validation. Seems they are close, but not quite there yet

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.