Loren
Loren

Reputation: 340

Json Schema Not working for nested Attributes

I am trying to add some validation to my json schema . I am validating json schema against json using this website https://www.jsonschemavalidator.net/. I am not able to put validation on eventPayload/totalAmount based on value present in eventName. It is not failing when it should fail. Should I give the whole path of eventName attribute as it is not present in eventPayload ? If yes, how to doenter image description here that.

    "totalAmount": {
      "type": [
        "integer",
        "number"
      ],
      "minLength": 1,
      "multipleOf": 0.01,
      "if": {
        "properties": {
          "eventName": {
            "enum": [
              "Test10",
              "Test12"
            ]
          }
        }
      },
      "then": {
        "properties": {
          "totalAmount": {
            "exclusiveMinimum": 0
          }
        }
      },
      "else": {
        "if": {
          "properties": {
            "eventName": {
              "enum": [
                "Test1",
                "Test2",
                "Test3"
              ]
            }
          }
        },
        "then": {
          "properties": {
            "totalAmount": {
              "exclusiveMaximum": 0
            }
          }
        }
      }
    }

Upvotes: 0

Views: 793

Answers (2)

Byted
Byted

Reputation: 657

It is not possible to reference values up the tree (e.g. totalAmount is below eventName), you have to define from the top down. Using oneOf (instead of if/then/else) and schema composition, you could solve it as follows (minimal example):

Schema:

{
    "$schema": "https://json-schema.org/draft/2019-09/schema",
    "type": "object",
    "properties": {
        "eventName": {
            "type": "string",
            "enum": ["Test10", "Test12", "Test1", "Test2", "Test3"]
        },
        "eventPayload": {
            "type": "object",
            "properties": {
                "totalAmount": {
                    "type": "number"
                }
            }
        }
    },
    "oneOf": [
        {
            "properties": {
                "eventName": {
                    "enum": ["Test10", "Test12"]
                },
                "eventPayload": {
                    "properties": {
                        "totalAmount": {
                            "exclusiveMinimum": 0
                        }
                    }
                }
            }
        },
        {
            "properties": {
                "eventName": {
                    "enum": ["Test1", "Test2", "Test3"]
                },
                "eventPayload": {
                    "properties": {
                        "totalAmount": {
                            "exclusiveMaximum": 0
                        }
                    }
                }
            }
        }
    ]
}

Here, we first define the general structure in the properties object (no validation yet, just the type of expected objects). Then, in the oneOf array we add the alternatives: If eventName is either "Test10" or "Test12" apply the exclusiveMinimum, if it is one of the others, apply exclusiveMaximum.

Any incoming json has to fulfill both the schema defined in properties and one of the schemas in oneOf. This way of layering schemas is how json schema implements composition. Using this schema and https://www.jsonschemavalidator.net/ we can verify that it

accepts

{
    "eventName": "Test12",
    "eventPayload": {
      "totalAmount": 5
    }
}

and

{
    "eventName": "Test2",
    "eventPayload": {
      "totalAmount": -5
    }
}

but rejects

{
    "eventName": "Test12",
    "eventPayload": {
      "totalAmount": -5
    }
}

and

{
    "eventName": "Test2",
    "eventPayload": {
      "totalAmount": 5
    }
}

Upvotes: 1

Ether
Ether

Reputation: 53966

The properties keyword in your if clause will evaluate to true if property eventName is not present. To ensure that it is, add "required": ["eventName"] to the condition.

Upvotes: 0

Related Questions