skip to Main Content

I am attempting to define two possible sets of patternProperties using anyOf, but I would like to exclude any properties that don’t fit either of those patterns. However, when defining additionalProperties: false after the two sets of patternProperties, I get an error that none of the properties match.

Here is some sample JSON data:

{
  "fruitbasket": {
    "apple": {
      "color": "green"
    },
    "pear": {
      "color": "green"
    },
    "banana": {
      "color": "yellow"
    },
    "apple_wrapper": {
      "material": "paper"
    },
    "pear_wrapper": {
      "material": "cloth"
    },
    "banana_wrapper": {
      "material": "none"
    }
  }
}

And here is my schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/responseobject",
  "definitions": {
    "responseobject": {
      "type": "object",
      "properties": {
        "fruitbasket": {
          "anyOf": [
            {
              "$ref": "#/definitions/fruit"
            },
            {
              "$ref": "#/definitions/wrapper"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "fruit": {
      "type": "object",
      "patternProperties": {
        "^(apple|pear|banana)$": {
          "type": "object",
          "properties": {
            "color": {
              "type": "string",
              "enum": [
                "green",
                "yellow",
                "red"
              ]
            }
          },
          "required": [
            "color"
          ],
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    },
    "wrapper": {
      "type": "object",
      "patternProperties": {
        "^(apple|pear|banana)_wrapper$": {
          "properties": {
            "material": {
              "type": "string",
              "enum": [
                "paper",
                "cloth",
                "none"
              ]
            }
          },
          "required": [
            "material"
          ],
          "additionalProperties": false
        }
      },
      "additionalProperties": false
    }
  }
}

If I remove "additionalProperties": false that is defined alongside even just one of the two patternProperties the schema validates. Is this level of strictness even possible in the current JSON schema? How should I go about allowing only two sets of patternProperties and no other property?

Here is an online validation example showing the errors: https://www.jsonschemavalidator.net/s/DQqnlLBT

2

Answers


  1. Chosen as BEST ANSWER

    Actually I think I found the answer. No need to use anyOf, just put the patternProperties one after the other:

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "$ref": "#/definitions/responseobject",
      "definitions": {
        "responseobject": {
          "type": "object",
          "properties": {
            "fruitbasket": {
              "type": "object",
              "patternProperties": {
                "^(apple|pear|banana)$": {
                  "$ref": "#/definitions/fruit"
                },
                "^(apple|pear|banana)_wrapper$": {
                  "$ref": "#/definitions/wrapper"
                }
              },
              "additionalProperties": false
            }
          }
        },
        "fruit": {
          "type": "object",
          "properties": {
            "color": {
              "type": "string",
              "enum": [
                "green",
                "yellow",
                "red"
              ]
            }
          },
          "required": [
            "color"
          ],
          "additionalProperties": false
        },
        "wrapper": {
          "properties": {
            "material": {
              "type": "string",
              "enum": [
                "paper",
                "cloth",
                "none"
              ]
            }
          },
          "required": [
            "material"
          ],
          "additionalProperties": false
        }
      }
    }
    

  2. Yes, you can remove the anyOf and have multiple patternProperties but you have undefined behavior for draft-07 when using $ref at the root of the schema, it must be wrapped in an allOf to be validated successfully, per the Specification.
    Only after 2019-09 was a root $ref allowed by the Specification.

    {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "allOf": [
            {
                "$ref": "#/definitions/responseobject"
            }
        ],
        "definitions": {
            "responseobject": {
                "type": "object",
                "properties": {
                    "fruitbasket": {
                        "type": "object",
                        "patternProperties": {
                            "^(apple|pear|banana)$": {
                                "type": "object",
                                "properties": {
                                    "color": {
                                        "type": "string",
                                        "enum": [
                                            "green",
                                            "yellow",
                                            "red"
                                        ]
                                    }
                                },
                                "required": [
                                    "color"
                                ],
                                "additionalProperties": false
                            },
                            "^(apple|pear|banana)_wrapper$": {
                                "properties": {
                                    "material": {
                                        "type": "string",
                                        "enum": [
                                            "paper",
                                            "cloth",
                                            "none"
                                        ]
                                    }
                                },
                                "required": [
                                    "material"
                                ],
                                "additionalProperties": false
                            }
                        },
                        "additionalProperties": false
                    }
                },
                "additionalProperties": false
            }
        }
    }
    

    passing instance

    {
        "fruitbasket": {
            "apple": {
                "color": "green"
            },
            "pear_wrapper": {
                "material": "paper"
            }
        }
    }
    

    failing instance

    {
        "fruitbasket": {
            "apple": {
                "color": "green"
            },
            "pears": {},
            "pear_wrapper": {
                "material": "paper"
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search