skip to Main Content

I’m relatively new to JSON Schema and I’m struggling to create a schema that enforces a specific constraint on an array field. The requirement is that the array field, named "selection", can contain values "a", "b", "c", or "none". However, the array cannot contain both "none" and any of the values "a", "b", or "c" simultaneously. Here’s an example to clarify:

Valid JSONs:

{
  "selection": ["a", "b", "c"]
}
{
  "selection": ["none"]
}

Invalid JSON:

{
  "selection": ["a", "b", "none"]
}

I’ve tried using oneOf with const and enum, but I couldn’t get it to work as expected. Can someone assist me in creating a JSON Schema that properly enforces this constraint?

Here’s the schema I’ve been working with:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "selection": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "const": "none"
                },
                {
                  "type": "string",
                  "enum": ["a", "b", "c"]
                }
              ]
            }
        }
    },
    "required": ["selection"]
}

Any suggestions or corrections to this schema would be greatly appreciated. Thank you!

2

Answers


  1. I got it working like this, but it requires draft2020-12 to support prefixItems if you want to support just a single entry of none in the array.

    You need unevaluatedItems which, when set to false allows the presence of none in the first oneOf schema that contains the enum causes it to not match.

    If you want none to be the only entry in the array when it exists, you’ll also need prefixItems. Although you could probably get away with maxItems:1 as well.

    It depends on how strict you want to be with your required format:

    {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "selection": {
          "oneOf": [
            {
              "type": "array",
              "items": {
                "type": "string",
                "enum": ["a", "b", "c"]
              },
              "unevaluatedItems": false
            },
            {
              "type": "array",
              "prefixItems": [
                {
                  "const": "none"
                }
              ]
            }
          ]
        }
      },
      "required": ["selection"]
    }
    
    
    // Passes:
    { selection: ["none"] }
    { selection: ["a","b","c"] }
    
    // Fails
    { selection: ["a","b","none"] }
    

    Vitest stackblitz

    Login or Signup to reply.
  2. If you want to use draft-04 – draft-2019-09, you can use this syntax:

    {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "additionalProperties": false,
        "properties": {
            "selection": {
                "oneOf": [
                    {
                        "type": "array",
                        "items": {
                            "enum": [
                                "a",
                                "b",
                                "c"
                            ]
                        },
                        "additionalItems": false
                    },
                    {
                        "type": "array",
                        "items": [
                            {
                                "const": "none"
                            }
                        ],
                        "additionalItems": false
                    }
                ]
            }
        },
        "required": [
            "selection"
        ]
    }
    

    OR

    {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "additionalProperties": false,
        "properties": {
            "selection": {
                "oneOf": [
                    {
                        "type": "array",
                        "items": {
                            "enum": [
                                "a",
                                "b",
                                "c"
                            ]
                        },
                        "additionalItems": false
                    },
                    {
                        "type": "array",
                        "items": {
                           "const": "none"
                        },
                        "maxItems": 1
                    }
                ]
            }
        },
        "required": [
            "selection"
        ]
    }
    

    The error messages are quite similar so either will work.

    Versions of JSON Schema prior to 2020-12 allowed the use of items: [] to indicate a tuple-like ordered index of values.

    The first example shows this pattern and uses additionalItems: false to prevent any other items to be added to the array.

    valid

    • {"selection": ["none"]}
    • {"selection": ["a","a","a"]}
    • {"selection": ["a"]}
    • {"selection": ["a","b"]}
    • etc…

    invalid

    • {"selection": ["a","a","none"]}
    • {"selection": ["none", "none"]}

    The second example uses maxItems and items: {} (object) where the index value can only be const: "none" and maxItems: 1 prevents any further indices to be populated.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search