Liviu Gelea
Liviu Gelea

Reputation: 361

Add additional properties to json array member schema

I'm trying to create 2 separate schemas for some json files which serve as scripts. One schema should contain all commands possible, while another one should only contain a subset of commands.

My thinking was I create minimal schema first:

{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
        "$schema": {},
        "commands": {
            "type": "array",
            "items":
            {
                "title": "One step of the migration",
                "type": "object",
                "minProperties": 1,
                "maxProperties": 1,

                "properties": {
                    "simple_command_1": {"type": "object"},
                    "simple_command_2": {"type": "object"},
                }
            }
        }
    }
}

which would validate json files like this:

{
    "$schema": "../../migration_schema_v1.json",
    "commands": [
        {"simple_command_1": {}},
        {"simple_command_1": {}},
        {"simple_command_2": {}},
        {"simple_command_2": {}},
    ]

I'm trying to avoid using the word extend but... I want to be able to create a second schema that has every command the first one has and an additional advanced_command_3. So I created this:

    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$ref": "/migration_schema_v1.json#/",
    "type": "object",
    "properties": {
        "foo": {
            "type": "object",
            "title": "this does work"
        },
        "commands": {
            "items":
            {
                "properties": {
                    "advanced_command_3": {"type": "object"}
                }
            }
        }
    }
}

I'm able to refer this second schema, and it does inherit everything from the first one, but I'm not really able to add any properties (commands)

I was however able to add additional properties in the root, next to "commands". See "foo" property.

Using allOf[] or $ref in the sub-property doesn't seem to make a difference.

Am I getting this all wrong? Thanks!

Upvotes: 0

Views: 179

Answers (1)

gregsdennis
gregsdennis

Reputation: 8428

I would actually break this into three schemas. The first contains the primary definition for your data, including all of the valid commands.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/definitions",
  "type": "object",
  "properties": {
    "$schema": {},
    "commands": {
      "type": "array",
      "items":
      {
        "title": "One step of the migration",
        "type": "object",
        "minProperties": 1,
        "maxProperties": 1,

        "properties": {
          "simple_command_1": {"type": "object"},
          "simple_command_2": {"type": "object"},
          "advanced_command_3": {"type": "object"}
        }
      }
    }
  }
}

The other two are your simple and advanced schemas. They work by defining that only the possibilities of the commands you want are required then referencing back to the definition schema to get the rest of the requirements.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/simple",
  "$ref": "definitions",
  "properties": {
    "commands": {
      "items": {
        "anyOf": [
          { "required": ["simple_command_1"] },
          { "required": ["simple_command_2"] }
        ]
      }
    }
  }
}

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/advanced",
  "$ref": "definitions",
  "properties": {
    "commands": {
      "items": {
        "anyOf": [
          { "required": ["simple_command_1"] },
          { "required": ["simple_command_2"] },
          { "required": ["advanced_command_3"] }
        ]
      }
    }
  }
}

I think this setup contains minimal repetition.


At this point you might be able to get away with what you're wanting to do with the extends thing. You'd have to extract the commands requirements in the simple schema into a $defs keyword and reference them from the advanced schema.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/simple",
  "$defs": {
    "simpleCommands": {
      "anyOf": [
        { "required": ["simple_command_1"] },
        { "required": ["simple_command_2"] }
      ]
    }
  },
  "$ref": "definitions",
  "type": "object",
  "properties": {
    "commands": {
      "items": { "$ref": "#/$defs/simpleCommands" }
    }
  }
}

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/advanced",
  "$ref": "definitions",
  "type": "object",
  "properties": {
    "commands": {
      "items": {
        "anyOf": [
          { "$ref" : "simple#/$defs/simpleCommands" },
          { "required": ["advanced_command_3"] }
        ]
      }
    }
  }
}

I haven't tested this though.

Upvotes: 1

Related Questions