Search code examples
jsonmongodbschemajsonschema

JSON Schema draft v4 - additional Properties error with anyOf


I get an additionalProperties error, I dont get the error when allowing additionalProperties before the anyOf and where i marked <-Here in the code.

Maybe some one knows and can explain the issue to me.

    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "title": "Media",
    "additionalProperties": false,
    "anyOf": [
        {
            "type": "object",
            "properties": {
                "series": {
                    "type": "object",
                    "title": "Series",
                    "properties": {
                        "folder-path": {
                            "type": "string",
                            "title": "Folder-path"
                        },
                        "seasons": {
                            "type": "array",
                            "title": "Seasons",
                            "additionalItems": false,
                            "uniqueItems": true,
                            "items": {
                                "type": "object",
                                "properties": {
                                    "folder-path": {
                                        "type": "string",
                                        "title": "Folder-path"
                                    },
                                    "season-name": {
                                        "type": "string",
                                        "title": "Season-name"
                                    },
                                    "episodes": {
                                        "type": "array",
                                        "title": "Episodes",
                                        "additionalItems": false,
                                        "uniqueItems": true,
                                        "items": {
                                            "type": "object",
                                            "properties": {
                                                "episode-name": {
                                                    "type": "string",
                                                    "title": "Episode-name"
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "title": "Description"
                                                },
                                                "video-file": {
                                                    "type": "string",
                                                    "title": "Video-file"
                                                },
                                                "cover-file": {
                                                    "type": "string",
                                                    "title": "Cover-file"
                                                }
                                            },
                                            "additionalProperties": false,
                                            "required": [
                                                "episode-name",
                                                "video-file"
                                            ]
                                        }
                                    }
                                },
                                "additionalProperties": false,
                                "required": [
                                    "folder-path",
                                    "season-name"
                                ]
                            }
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "folder-path"
                    ]
                }
            },
            "additionalProperties": false, <-Here
            "required": [
                "series"
            ]
        },
        {
            "type": "object",
            "properties": {
                "movie": {
                    "type": "object",
                    "title": "Movie",
                    "properties": {
                        "video-file": {
                            "type": "string",
                            "title": "Video-file"
                        },
                        "sub-titles": {
                            "type": "array",
                            "title": "Subtitle-files",
                            "additionalItems": true,
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "video-file"
                    ]
                }
            },
            "additionalProperties": false, <-Here
            "required": [
                "movie"
            ]
        }
    ]
}

Solution

  • No instance will ever pass this schema because you have an additionalProperties: false at the root. This constraint doesn't allow any properties which are undefined at the root, which includes all subschemas (anyOf, allOf, oneOf) because they are not in the same scope as the root schema.

        "$schema": "http://json-schema.org/draft-04/schema#",
        "type": "object",
        "title": "Media",
        "additionalProperties": false,  <---THIS
        "anyOf": [
    ...
    

    Maintaining the constraint inside your anyOf subschema would be the correct way to go for this example.

    {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "title": "Media",
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "series": {
              "type": "object",
              "title": "Series",
              "properties": {
                "folder-path": {
                  "type": "string",
                  "title": "Folder-path"
                },
                "seasons": {
                  "type": "array",
                  "title": "Seasons",
                  "additionalItems": false,
                  "uniqueItems": true,
                  "items": {
                    "type": "object",
                    "properties": {
                      "folder-path": {
                        "type": "string",
                        "title": "Folder-path"
                      },
                      "season-name": {
                        "type": "string",
                        "title": "Season-name"
                      },
                      "episodes": {
                        "type": "array",
                        "title": "Episodes",
                        "additionalItems": false,
                        "uniqueItems": true,
                        "items": {
                          "type": "object",
                          "properties": {
                            "episode-name": {
                              "type": "string",
                              "title": "Episode-name"
                            },
                            "description": {
                              "type": "string",
                              "title": "Description"
                            },
                            "video-file": {
                              "type": "string",
                              "title": "Video-file"
                            },
                            "cover-file": {
                              "type": "string",
                              "title": "Cover-file"
                            }
                          },
                          "additionalProperties": false,
                          "required": [
                            "episode-name",
                            "video-file"
                          ]
                        }
                      }
                    },
                    "additionalProperties": false,
                    "required": [
                      "folder-path",
                      "season-name"
                    ]
                  }
                }
              },
              "additionalProperties": false,
              "required": [
                "folder-path"
              ]
            }
          },
          "additionalProperties": false,
          "required": [
            "series"
          ]
        },
        {
          "type": "object",
          "properties": {
            "movie": {
              "type": "object",
              "title": "Movie",
              "properties": {
                "video-file": {
                  "type": "string",
                  "title": "Video-file"
                },
                "sub-titles": {
                  "type": "array",
                  "title": "Subtitle-files",
                  "additionalItems": true,
                  "items": {
                    "type": "string"
                  }
                }
              },
              "additionalProperties": false,
              "required": [
                "video-file"
              ]
            }
          },
          "additionalProperties": false,
          "required": [
            "movie"
          ]
        }
      ]
    }
    

    passing instances:

    {
      "series": {
        "folder-path": "1"
      }
    }
    
    {
      "movie": {
        "video-file": "1"
      }
    }
    

    failing instances

    {
      "movie": {
        "video-file": "1"
      },
      "stack": 1
    }
    
    {
      "series": {
        "folder-path": "1"
      },
      "stack": 1
    }
    
    

    src: Understanding JSON Schema Scope