1

I have a schema where I have an array (inside the transmit object) which could possibly have one of two options (A or B).

I have attached both the schema and sample data (that is actually getting validated, when it should have thrown an error).

under transmitDataDef->items, I have tried "anyOf", "oneOf", "type" and they all yield no-errors even though the data does not match (data contains optionC that is not defined anywhere)

I am using jsonschema python library. I have also tried this schema + data in https://www.jsonschemavalidator.net/ with same results.

Schema:

{
  "definitions": {
    "optionADef": {
      "type": "object",
      "properties": {
        "pattern": {
          "type": "string",
          "enum": [
            "random",
            "fixed"
          ]
        },
        "startbyte": {
          "type": "number"
        }
      },
      "required": [
        "startbyte"
      ],
      "additionalProperties": false
    },
    "optionBSubItemDef": {
      "type": "object",
      "properties": {
        "value": {
          "type": "number",
          "minimum": 0
        }
      }
    },
    "optionBSettingsDef": {
      "type": "object",
      "properties": {
        "sequence": {
          "type": "number",
          "minimum": 0
        }
      }
    },
    "optionBDataDef": {
      "type": "object",
      "properties": {
        "subitem": {
          "ref": "#/definitions/optionBSubItemDef"
        }
      }
    },
    "optionBDef": {
      "type": "object",
      "properties": {
        "_data": {
          "ref": "#/definitions/optionBDataDef"
        },
        "_settings": {
          "$ref": "#/definitions/optionBSettingsDef"
        }
      },
      "required": [
        "_data"
      ],
      "additionalProperties": false
    },
    "transmitDataDef": {
      "type": "array",
      "minItems": 1,
      "maxItems": 1,
      "items": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "optionA": {
                "ref": "#/definitions/optionADef"
              }
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "optionB": {
                "ref": "#/definitions/optionBDef"
              }
            },
            "additionalProperties": false
          }
        ]
      }
    },
    "transmitSettingsDef": {
      "type": "object",
      "properties": {
        "length": {
          "type": "number",
          "minimum": 0,
          "maximim": 8
        }
      }
    },
    "transmitDef": {
      "type": "object",
      "properties": {
        "_data": {
          "ref": "#/definitions/transmitDataDef"
        },
        "_settings": {
          "$ref": "#/definitions/transmitSettingsDef"
        }
      },
      "required": [
        "_data"
      ],
      "additionalProperties": false
    },
    "bundleDef": {
      "type": "object",
      "properties": {
        "transmit": {
          "$ref": "#/definitions/transmitDef"
        }
      },
      "oneOf": [
        {
          "required": [
            "transmit"
          ]
        }
      ],
      "additionalProperties": false
    }
  },
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "bundle": {
      "$ref": "#/definitions/bundleDef"
    }
  },
  "required": [
    "name",
    "bundle"
  ]
}

Sample data:

{
  "name": "test1",
  "bundle": {
    "transmit": {
      "_settings": {
        "length": 0
      },
      "_data": [
        {
          "optionC": {
            "_settings": {
              "sequence": 150
            },
            "data1": [
              {
                "subitem": {
                  "value": 100
                }
              }
            ]
          }
        }
      ]
    }
  }
}

I expect the validation to catch "optionC" and flag it as an error. If I had optionB instead of optionC, i expect it to flag "data1" as an invalid item.

Bhakta Raghavan
  • 664
  • 6
  • 16

1 Answers1

1

You have the right approach. I validated this using the following schema and instance using https://jsonschema.dev

Schema:

{
  "properties": {
    "_data": {
      "type": "array",
      "items" : {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "inline": true
            },
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "rewrite": true
            },
            "additionalProperties": false
          }
        ]
      }
    }
  }
}

Instance :

{
  "_data": [
    {
      "optionC": {
        "_settings": {
          "sequence": 150
        },
        "data1": [
          {
            "subitem": {
              "value": 100
            }
          }
        ]
      }
    }
  ]
}

There is a problem with something other than your use of "anyOf", which is correct.

It's actually something FAR simpler...

You've used "ref" as opposed to "$ref" in your schema in quite a few places. Unknown keywords are ignored, and so your references were not working.

If it's any consolation, it took me quite a while to debug!

Relequestual
  • 11,631
  • 6
  • 47
  • 83
  • Thank you Relequestual. It was the ref -> $ref that fixed everything. I feel terrible, having looked at it so many times, that I never realized it was this.. I have accepted this solution.. – Bhakta Raghavan May 28 '19 at 12:33
  • No problem. As I said, it took me a while to work out also! – Relequestual May 28 '19 at 12:33
  • Is there a way to debug this? I mean like a framework that spits out logs that can indicate that certain keywords were ignored? That would help catch such issues? – Bhakta Raghavan May 28 '19 at 12:35
  • No. I do this manually by setting schemas to `false` to see if it fails. A JSON Schema Linter would be nice, but that's in the works. If you'd like to encourage me to work faster, please see the link in my profile =] – Relequestual May 28 '19 at 12:37