jsonjsonschema

How can I exclude certain properties and keys from a self referential JSON Schema?


I have a schema like:

{
  "$id": "http://example.com/names.json",
  "type": "object",
  "required": ["id", "name"],
  "additionalProperties": false,
  "properties": {
    "name": {
      "type": "string"
    },
    "id": {
      "type": "string"
    },
    "subscriptions": {
      "type": "object"
    }
  }
}

I then want to add the ability to create drafts that are stored on the object, for this I want to add a "draftVersion" property, that can take any and all of the properties of the main object. I know I can do this by altering the schema like:

{
  "$id": "http://example.com/names.json",
  "type": "object",
  "required": ["id", "name"],
  "additionalProperties": false,
  "properties": {
    "name": {
      "type": "string"
    },
    "id": {
      "type": "string"
    },
    "subscriptions": {
      "type": "object"
    },
    "draftVersion": {
      "$ref": "#"
    }
  }
}

However, this will then allow for deep recursiveness, such as an object like:

{
  "name": "abc",
  "id": "123"
  "draftVersion": {
    "name": "abc",
    "id": "123"
    "draftVersion": {
    
    }
  }
}

So i'd like to be able to exclude draftVersion from being a property that can exist on draftVersion. I'd also like to be able to exclude the "additionalProperties" and "required" keys from the draftVersion object, so that an object such as:

{
  "name": "abc",
  "id": "123"
  "draftVersion": {
    "subscriptions": {
      "id": 123
    }
  }
}

would be valid. It doesn't seem that altering the draftVersion property to include a not would work e.g.

"draftVersion": {
  "$ref": "#",
  "not": {
    "anyOf": [
      {
        "required": ["draftVersion"]
      }
    ]
  }
}

Is there a way to compose such a schema?


Solution

  • Here are two versions, draft-07 and draft-04. draft-04 requires a little more magic because it doesn't recognize the false keyword for object schemas.

    draft-07

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "allOf": [
        { "$ref": "#/definitions/rootSchema" },
        { "required": ["name", "id"] }
      ],
      "additionalProperties": false,
      "properties": {
        "name": {},
        "id": {},
        "subscriptions": {},
        "draftVersion": {
          "properties": { "draftVersion": false }
        }
      },
      "definitions": {
        "rootSchema": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "id": { "type": "string" }
          }
        }
      }
    }
    

    draft-04

    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "allOf": [
        { "$ref": "#/definitions/rootSchema" },
        { "required": ["name", "id"] }
      ],
      "additionalProperties": false,
      "properties": {
        "name": {},
        "id": {},
        "subscriptions": {},
        "draftVersion": {
          "properties": { "draftVersion": { "not": {} } }
        }
      },
      "definitions": {
        "rootSchema": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "id": { "type": "string" }
          }
        }
      }
    }