Home > database >  Conditional validation based on array element - Avoid warning 'missing type "object"
Conditional validation based on array element - Avoid warning 'missing type "object"

Time:05-04

I have a JSON array containing objects with key value pairs.

[
    { "name": "foo" },
    { "name": "bar" }
]

If one the name's equals null I want to set maxItems to 1.

My schema looks like this:

{
    "type": "array",
    "minItems": 1,
    "items": {
        "type": "object",
        "properties": {
            "name": {
                "enum": [null, "foo", "bar"]
            }
        },
        "required": [
            "name"
        ]
    },
    "if": {
        "contains": { "properties": { "name": { "const": null } } }
    },
    "then": {
        "maxItems": 1
    }
}

It basically works but outputs a warning at compile time:

strict mode: missing type "object" for keyword "properties" at "#/if/contains" (strictTypes)

I am understanding that properties is only a keyword for objects and I am applying it to an instance of array here (actually meaning: properties of one of the array's objects), but I have no idea how to solve this properly.

A complete AJV minimal example looks like this:

const Ajv = require('ajv');
const ajv = new Ajv();

const schema = {
    "type": "array",
    "minItems": 1,
    "items": {
        "type": "object",
        "properties": {
            "name": {
                "enum": [null, "foo", "bar"]
            }
        },
        "required": [
            "name"
        ]
    },
    "if": {
        "contains": { "properties": { "name": { "const": null } } }
    },
    "then": {
        "maxItems": 1
    }
};

const data = [
    { name: 'foo' },
    { name: 'bar' }
];

const data2 = [
    { name: null }
];

const data3 = [
    { name: 'foo' },
    { name: null }
];

const validate = ajv.compile(schema); // strict mode: missing type "object" for keyword "properties" at "#/if/contains" (strictTypes)
console.log(validate(data)); // true
console.log(validate(data2)); // true
console.log(validate(data3)); // false

CodePudding user response:

The specification does not mandate that "type": "object" must appear with object-specific keywords such as properties. (Indeed, it's often useful to mix and match keywords that correspond to different types, to allow for flexible data input.) Nevertheless, the ajv implementation insists upon doing this.

Your options at this point are adding the extra keywords, pleading with the implementation author to fix this behaviour, or switch to a different implementation.

CodePudding user response:

The definition of the keyword contains says that its value must be a valid JSON schema. So this warning makes sense. Why not simply adding a "type": "object" to the schema at contains?

In your eyes, as a human, this might be not necessary because you already 'know' that the values are objects, but the validator does expect a full schema here to apply to each array value.

  • Related