Search code examples
jsonschema

JSON Schema Draft-07 schema For dynamic keys in an enum


Is there way to define a draft-07 JSON Schema for keys that are not predefined but, each key is constrained to an enum? The json sample will look like:

{
    "letters": {
        "a": [1, 2, 3],
        "b": [2, 3]
    }
}

Where keys in the letters object are constrained by an enum: key in ["a", "b", "c"].

I want to be able to use any number of keys as long as they are in the enum such that the following json can also pass:

{
    "letters": {
        "a": [1, 2, 3],
    }
}

Solution

  • keys that are not predefined but each key is constraint to an enum

    use additionalProperties to create an object schema constrained to an enum with dynamic properties

    {
      "type": "object",
      "properties": {
        "letters": {
          "type": "object",
          "additionalProperties": {
              "enum": [1,2,3]
          }
        }
      }
    }
    

    This will validate

    {
      "letters": {
        "a": 2,
        "ddd": 1
      }
    }
    

    Where keys in the letters object are constraint by an enum: key in ["a", "b", "c"].

    I want to be able to any number of keys as long as they are in the enum

    The keyword(s) which may work are patternProperties or propertyNames .

    {
      "type": "object",
      "properties": {
        "letters": {
          "patternProperties": {
            "a|b|c": {
              "enum": [1,2,3]
            }
          }
        }
      }
    }
    

    --

    This would validate

    {
      "letters": 
        "a": 1,
        "b": 2, 
        "c": 3
    }
    

    OR

    This one can be tricky because an enum can define any JSON Schema schema, such as: boolean, number, integer, null, object, or array. These are invalid JSON property(key) names. Only string schemas SHALL be defined in propertyNames enumeration.

    {
      "type": "object",
      "properties": {
        "letters": {
          "propertyNames": {
            "enum": ["a","b","c"]
          },
          "additionalProperties": {
            "enum": [1,2,3]
          }
        }
      }
    }
    

    This would validate.

    {
      "letters": {
        "a": 1,
        "b": 2,
        "c": 3
      }
    }
    

    If you want the values to be an array of numbers, you should modify the additionalProperties schema to

    "additionalProperties": {
      "type": "array",
      "items": [{"type": "number"]}
    }
    

    This would validate

    {
        "letters": {
            "a": [1, 2, 3]
        }
    }