JSON Schema with array of different object types with mandatory property fails to validate

34 Views Asked by At

I edited the original schema to show my real problem

i am having this JSON schema

 {
      "type": "object",
      "properties": {
        "stages": {
          "type": "array",
          "minItems": 1,
          "items": {
            "anyOf": [
              {"$ref": "clone.json#/clone"},
              {"$ref": "clone.json#/build"}
            ]
          }
        }
      }
    }

With Ref schema (clone.json) as:

{    
    "proper": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
                      "name1": {"type": "string"},
                      "name2": {"type": "string"}
                    },
                    "required": ["name2"]
    },
    "clone": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
            "clone": {
                "anyOf": [
                    {
                        "$ref": "#/proper"
                    },
                    {
                        "type": "object",
                        "additionalProperties": false,
                        "properties": {
                            "cloneName": {
                                "description": "The repo name",
                                "type": "string"
                            }
                        },
                        "required": [
                          "cloneName"
                        ]
                    }
                ]
            }
        }
    },
    "build": {
        "type": "object",
        "properties": {
            "build": {
                "anyOf": [
                    {
                        "$ref": "#/proper"
                    },
                    {
                        "type": "object",
                        "additionalProperties": false,
                        "properties": {
                            "buildName": {
                                "description": "The repo name",
                                "type": "string"
                            }
                        },
                        "required": [
                          "buildName"
                        ]
                    }
                ]
            }
        }
    }
}

BTW:In my real schema i am getting the "properties" section from a different schema as $ref

and as test Json i am using

{
     "stages": [
          {
                "clone": {}
          },
          {
                "build": {}
          }
     ]
}

and (at least in vscode) i am not getting any worning for missing required parameter

can you please help me understand what am I doing wrong? thanks

1

There are 1 best solutions below

3
Jeremy Fiel On

The first issue is your root schema has stages defined but you are not constraining the schema to additionalProperties: false. This is not a requirement, but if you pass any other property name at the root, it does not consider any validation constraints. As in your example instance, your root element is test2 and not stages, so no validation is applied against your data instance.

This will fix the first issue.

{
    "stages": [
        {
            "test": {}
        }
    ]
}

Secondly, your anyOf subschemas are unconstrained for additional properties. This means your second anyOf subschema passes validation of test: {} because you have no constraints on test in the second subschema. One way you can constrain these type of schemas is to use additionalProperties: false in each subschema; then you will see the error for missing required

             "items": {
                "anyOf": [
                    {
                        "type": "object",
                        "additionalProperties": false,  <--- HERE
                        "properties": {
                            "test": {
                                "type": "object",
                                "properties": {
                                    "name1": {
                                        "type": "string"
                                    },
                                    "name2": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "name2"
                                ]
                            }
                        }
                    },
                    {
                        "type": "object",
                        "additionalProperties": false,  <---HERE
                        "properties": {
                            "test1": {
                                "type": "object",
                                "properties": {
                                    "name1": {
                                        "type": "string"
                                    },
                                    "name2": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "name1"
                                ]
                            }
                        }
                    }
                ]
            }