50

I have the following JSON output data:

{
   "label_name_0" : 0,
   "label_name_5" : 3,
   .
   .
   .
   "label_name_XXX" : 4
}

The output is simple: a key[1] name associated with integer value. If the key name doesn't change, I can easily come up with JSON Schema similar to this:

    {
        "type": "array"
        "title": "Data output",
        "items" :{ 
            "properties": {
                "label_name": {
                   "type": "integer",
                   "default": 0,
                   "readonly": True,
            }
        }
    },

Since the key name itself is not known and keep changing, I have to design schema for it. The only thing I know is that the key is string and not more than 100 characters. How do I define a JSON Schema for the key lable_name_xxx that keeps changing.

[1] Not sure if I am using the right terminology

Cory
  • 14,865
  • 24
  • 57
  • 72

3 Answers3

60

On json-schema.org you will find something appropriate in the File System Example section. You can define patternProperties inside an object.

{
    "type": "object",
    "properties": {
        "/": {}
    },
    "patternProperties": {
        "^(label_name_[0-9]+)+$": { "type": "integer" }
    },
    "additionalProperties": false,
 }

The regular expression (label_name_[0-9]+)+ should fit your needs. In JSON Schema regular expressions are explicitly anchored with ^ and $. The regular expressions defines, that there has to be at least one property (+). The property consists of label_name_ and a number between 0 and 9 whereas there has to be at least one number ([0-9]+), but there can also arbitrary many of them.

By setting additionalProperties to false it constrains object properties to match the regular expression.

xmedeko
  • 7,336
  • 6
  • 55
  • 85
Konrad Reiche
  • 27,743
  • 15
  • 106
  • 143
  • 4
    dead link. Documentation is at https://json-schema.org/understanding-json-schema/reference/object.html#pattern-properties – Matthias Urlichs Mar 19 '19 at 19:25
  • See @mrtnlrsn answer for a simpler solution that doesn't restrict the pattern of the key with a regular expression (if that isn't desired). – Romain G Jun 10 '23 at 18:49
27

As Konrad's answer stated, use patternProperties. But use in place of properties, which is not needed, and I think Konrad just pasted from his reference example that was expecting a path starting with /. In the example below, the pattern match regex .* accepts any property name and I am allowing types of string or null only by using "additionalProperties": false.

  "patternProperties": {
    "^.*$": {
      "anyOf": [
        {"type": "string"},
        {"type": "null"}
      ]
    }
  },
  "additionalProperties": false
user3071284
  • 6,955
  • 6
  • 43
  • 57
pink spikyhairman
  • 2,391
  • 1
  • 16
  • 13
  • `additionalProperties` is useless for type constraint, it's declared by `anyOf`. – xmedeko Jul 27 '21 at 12:15
  • Pattern should be `^.+$` if the property name must not be empty. Then, the `"additionalProperties": false` must be set, too. – xmedeko Jul 27 '21 at 12:18
15

Simpler solution than patternProperties, since OP does not have any requirement on the key names (documentation):

{
    "type": "object",
    "additionalProperties": {
        "type": "integer",
        "default": 0,
        "readonly": true,
    }        
}

default and readonly included because they were included in the OP's initial suggestion, but they are not required.

mrtnlrsn
  • 1,105
  • 11
  • 19
  • 3
    Thank you. This is exactly what I was looking for when searching for the same question as OP. Yours is the simplest solution, since no regular expression or limitation for key names is required. This should be the accepted answer. – jiri-vyc May 02 '22 at 09:28