Search code examples
arraysobjectjsonschemarequired

JSON Schema for array of different types with mandatory property fails validation


I created the following draft4 schema:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "$id": "catalog.structs.schema.json",
    "definitions": {
         "geography": {
            "type": "object",
            "description": "Geographical location which may or may not be part of a hierarchy.",
            "properties": {
                "geography_type": {
                    "type": "string",
                    "enum": ["union", "country", "state"] 
                },
                "name": {
                    "type": "string",
                    "enum": ["Turkey", "Netherlands"]
                },
                "parent": {
                    "type": "object",
                    "$ref": "#/definitions/geography"
                }
            },
            "required": ["name"]
        },
        "geography_group": {
            "type": "array",
            "description": "A grouping of discrete geographies that are not necessarily in a common hierarchy.",
            "items": {
                "type" : "object",
                "$ref": "#/definitions/geography"
            }
        }
    },
    "oneOf": [{
        "properties": {
            "geography": { "type": "object", "$ref": "#/definitions/geography"},
            "geography_group" : { "type": "object", "$ref": "#/definitions/geography_group"}
        },
        "additionalProperties": false
    }]
}

The following validates correctly against the schema

{"geography":{"name":"Turkey", "geography_type":"country"}}

However, the following fails stating that the required property name is missing.

{"geography_group":[{"geography":{"name":"Turkey", "geography_type":"country"}}]}

If I remove "required": ["name"] it works, but I don't want to remove this.

What am I doing wrong?


Solution

  • There are a few misconceptions here, but you broadly have the right idea.

    I'm not sure what you believe the oneOf is doing here. In this case, it simply isn't required, and you can put properties and additionalProperties straight in the root schema.

    In terms of your problem, while you've defined geography as a property at the root level, you haven't done so for an item object in the geography_group value array.

    You want to change your geograph_group definition to the following...

    "geography_group": {
          "type": "array",
          "description": "A grouping of discrete geographies that are not necessarily in a common hierarchy.",
          "items": {
            "properties": {
              "geograph": {
                "$ref": "#/definitions/geography"
              }
            }
          }
        }
    

    As an aside, in draft-04 of JSON Schema, any keywords alongside $ref are ignored.

    The key you use in the definitions object has no bearing on the validation of your data.