JSON schema anyOf validation based on one of properties

Fo. picture Fo. · Apr 14, 2016 · Viewed 17.7k times · Source

I'm having difficulty figuring out how to validate an array of objects based on the value of one of the properties. So where I have a JSON object like:

{
    "items": [
        {
            "name": "foo",
            "otherProperty": "bar"
        },
        {
            "name": "foo2",
            "otherProperty2": "baz",
            "otherProperty3": "baz2"
        },
        {
            "name": "imInvalid"
        }
    ]
}

I would like to say that

  1. items can contain anyOf objects where name can be "foo" or "foo2"
  2. if it's "foo" then the only valid other property (required) is "otherProperty"
  3. if the name is "foo2" then the only valid other properties are "otherProperty2" and "otherProperty3" both required
  4. No other value for "name" than "foo" and "foo2" is valid
  5. The objects themselves are optional in the items array, and some might be repeated.

I've tried all kinds of things but I can't seem to get a failure when I validate. For example, the name "imInvalid" should be causing a validation error. This is my latest iteration of the schema. What am I missing?

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "required": ["items"],
    "properties": {
        "items": {
            "type": "array",
            "minItems": 1,
            "additionalProperties": false,
            "properties": {
                "name": {
                    "anyOf": [
                        {
                            "type": "object",
                            "required": ["name", "otherProperty"],
                            "additionalProperties": false,
                            "properties": {
                                "otherProperty": { "type": "string" },
                                "name": { "enum": [ "foo" ] }
                            }
                        },{
                            "type": "object",
                            "required": ["name", "otherProperty2", "otherProperty3" ],
                            "additionalProperties": false,
                            "properties": {
                                "otherProperty2": { "type": "string" },
                                "otherProperty3": { "type": "string" },
                                "name": { "enum": [ "foo2" ] }
                            }
                        }
                    ]
                }
            }
        }
    }
}

Answer

user1270191 picture user1270191 · Apr 14, 2016

You've got the basic idea of using enum to separate what's matching, but there are a couple of mistakes here:

  • Json schema arrays don't have properties, they have items.
  • Within those properties you're defining name as an attribute that then holds other json schema objects.
  • In the second branch of your schema you defined otherProperty3 but in your sample that property is called anotherProperty3

Try this slightly modified version:

{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"required": ["items"],
"properties": {
    "items": {
        "type": "array",
        "minItems": 1,
        "additionalProperties": false,
        "items": {
            "anyOf": [
                {
                    "type": "object",
                    "required": ["name", "otherProperty"],
                    "additionalProperties": false,
                    "properties": {
                        "otherProperty": { "type": "string" },
                        "name": { "enum": [ "foo" ] }
                    }
                },{
                    "type": "object",
                    "required": ["name", "otherProperty2", "anotherProperty3" ],
                    "additionalProperties": false,
                    "properties": {
                        "otherProperty2": { "type": "string" },
                        "anotherProperty3": { "type": "string" },
                        "name": { "enum": [ "foo2" ] }
                    }
                }
            ]
        }
    }
}
}