1

I have the following JSON which validates against my current schema:

    {
      "information": [
        {
          "value": "closed",
          "type": "power"
        },
        {
          "value": "on",
          "type": "door"
        }
      ]
    }

However, I want this validation to fail (since open/closed should relate to door, and on/off should only relate to power.

How can I tie the two together?

My current working schema:

  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "Type": {
      "type": "string",
      "enum": ["power", "door"]
    },
    "Power": {
      "type": "string",
      "enum": ["on", "off"]
    },
    "Door": {
      "type": "string",
      "enum": ["open", "closed"]
    },
    "InformationField": {
      "type": "object",
      "required": [ "type", "value" ],
      "properties": {
        "label": { "type": "string" },
        "value": {
          "anyOf": [
            { "$ref": "#/definitions/Power"},
            { "$ref": "#/definitions/Door"}
          ]
        },
        "type": { "$ref": "#/definitions/Type" }
      }
    },
    "Information": {
      "type": "array",
      "items": { "$ref": "#/definitions/InformationField" }
    },
  },
  "properties": {
    "information": { "$ref": "#/definitions/Information" }
  },
}

I have a lot of types, so I want to do this in the cleanest way possible.

Here is one of my attempts, which fails to validate correctly:

{ 
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {
    "Type": {
      "type": "string",
      "enum": ["power", "door"]
    },
    "Power": {
      "type": "string",
      "enum": ["on", "off"]
    },
    "Door": {
      "type": "string",
      "enum": ["open", "closed"]
    },
    "InformationField": {
      "type": "object",
      "required": [ "label", "value" ],
      "properties": {
        "label": { "type": "string" },
        "type": { "$ref": "#/definitions/Type" }
      },
      "anyOf": [
        {
          "if": {
           "properties": { "type": { "const": "power" } }
          },
          "then": {
            "properties": { "value": { "$ref": "#/definitions/Power" } }
          }
        },
        {
          "if": {
            "properties": { "type": { "const": "door" } }
          },
          "then": {
            "properties": { "value": { "$ref": "#/definitions/Door" } }
          }
        }
      ]
    },
    "Information": {
      "type": "array",
      "items": { "$ref": "#/definitions/InformationField" }
    },
  },
  "properties": {
    "information": { "$ref": "#/definitions/Information" }
  },
}

(Validates, even though it shouldn't ...)

1 Answer 1

2

Changed anyOf to allOf in my attempt, which fixes validation.

My reasoning as to why this works:

From the anyOf JSON schema spec:

5.5.4.2. Conditions for successful validation

An instance validates successfully against this keyword if it validates successfully against at least one schema defined by this keyword's value.

If my first if condition is false, then it doesn't evaluate the then, and is therefore valid.

Using allOf evaluates every condition's validation (not the condition itself).

Sign up to request clarification or add additional context in comments.

1 Comment

Alternativly, you could add else: false to your if/then schemas.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.