Property has not been defined and the schema does not allow additional properties

Viewed 3372

I'm getting the below error while trying to validate the schema - v7 draft. Appreciate your help in resolving this error.

I'm trying to build the schema based on the conditional enum value from header. The attribute 'salary' type needs to vary based on the condition choose in the header.

ERROR

Property 'salary' has not been defined and the schema does not allow additional properties.

JSON schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "EmployeeHeader": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "object",
      "properties": {
        "empType": {
          "type": "string",
          "enum": [
            "FULLTIME",
            "CONTRACT"
          ]
        }
      },
      "required": [
        "empType"
      ]
    },
    "EmployeeDetail": {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "type": "array",
      "items": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
          "workInfo": {
            "$schema": "http://json-schema.org/draft-07/schema#",
            "type": "object",
            "properties": {
              "jobtitle": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              }
            },
            "required": [
              "jobtitle"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "workInfo"
        ],
        "additionalProperties": false
      },
      "minItems": 1
    }
  },
  "if": {
    "properties": {
      "EmployeeHeader": {
        "properties": {
          "empType": {
            "const": "FULLTIME"
          }
        }
      }
    }
  },
  "then": {
    "properties": {
      "EmployeeDetail": {
        "items": {
          "properties": {
            "workInfo": {
              "properties": {
                "salary": {
                  "type": "object",
                  "properties": {
                    "regular": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1000000,
                      "exclusiveMaximum": false,
                      "multipleOf": 0.01
                    },
                    "bonus": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1000000,
                      "exclusiveMaximum": false,
                      "multipleOf": 0.01
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "else": {
    "properties": {
      "EmployeeDetail": {
        "items": {
          "properties": {
            "workInfo": {
              "properties": {
                "salary": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1000000,
                  "exclusiveMaximum": false,
                  "multipleOf": 0.01
                }
              }
            }
          }
        }
      }
    }
  },
  "required": [
    "EmployeeHeader",
    "EmployeeDetail"
  ],
  "additionalProperties": false
}

SAMPLE PAYLOAD

{
  "EmployeeHeader": {
    "empType": "FULLTIME"
  },
  "EmployeeDetail": [
    {
      "workInfo": {
        "jobtitle": "Software Engineer",
        "salary": {
          "regular": 4000,
          "bonus": 5000
        }
      }
    }
  ]
}
1 Answers

Issue

The additionalProperties keyword only considers the properties and patternProperties defined in the immediate subschema where it appears. Since you define the “salary” property only within your then and else keywords, it is treated as an illegal additional property.

Solution

Already introduce the “salary” property in the subschema’s properties where the additionalProperties: false are defined as well. At least as simple boolean schema true. In other circumstances, one could also include all common attributes that appear in both the then and else keywords to reduce duplication, but in your particular case that’s hardly an option.

Additional Note

Generally speaking, if/then/else should only be used for additional constraints (e.g. minimum/maximum/required) but not to introduce completely new properties especially when using patternProperties or additionalProperties.

Related