Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues with additonal properties evaluation #140

Closed
sashkamal opened this issue Mar 9, 2016 · 6 comments
Closed

Issues with additonal properties evaluation #140

sashkamal opened this issue Mar 9, 2016 · 6 comments
Labels

Comments

@sashkamal
Copy link

sashkamal commented Mar 9, 2016

In the following code, in the interface section is referenced in the device section. Additional property is set to false and required is mode. But the validation fails even if we give the right properties of interface.
If the required mode or the right enumeration for mode is not given, it throws the right error.

Seems additional properties is not evaluated properly. Can you check.

Here is the error:
Invalid: data.configs.vid.desc.device.mgt0 should NOT have additional properties, data.configs.vid.desc.device.mgt0 should NOT have additional properties, data.configs.vid.desc.device.mgt0 should NOT have additional properties, data.configs.vid.desc.device.mgt0 should NOT have additional properties

var Ajv = require('ajv');
var ajv = Ajv({allErrors: true});

var schema = {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "test schema version 1",
    "definitions": {
        "interface": {
            "properties": {
                "mode": {
                    "enum": [
                        "STATIC",
                        "DHCP",
                    ]
                },
                "address": {
                    "type": "string",
                    "format": "ipv4"
                },
                "netmask": {
                    "type": "string",
                    "format": "ipv4"
                },
                "network": {
                    "type": "string",
                    "format": "ipv4"
                },
                "gateway": {
                    "type": "string",
                    "format": "ipv4"
                },
            }
        },
        "content": {
            "properties": {
                "misc": {
                    "type": "string"
                },
                "id1": {
                    "type": "string"
                },
                "id2": {
                    "type": "string"
                },
                "device": {
                    "type": "object",
                    "properties": {
                        "Name": {
                            "type": "string"
                        },
                        "mgt0": {
                            "type": "object",
                            "$ref": "#/definitions/interface",
                            "additionalProperties": false,
                            "required": [
                                "mode"
                            ]
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "mgt0"
                    ]
                }
            },
            "additionalProperties": false,
            "required": [
                "id1",
                "id2",
                "device",
            ]
        }
    },
    "type": "object",
    "properties": {
        "misc": {
            "type": "string"
        },
        "version": {
            "type": "string"
        },
        "configs": {
            "type": "object",
            "properties": {
                "vid": {
                    "type": "object",
                    "properties": {
                        "desc": {
                            "type": "object",
                            "$ref": "#/definitions/content"
                        }
                    },
                    "required": [
                        "desc"
                    ]
                }
            },
            "required": [
                "vid"
            ]
        }
    },
    "required": [
        "version",
        "configs"
    ]
};

var validate = ajv.compile(schema);

test({"configs":{"vid":{"desc":{"device":{"Name":"Cam","mgt0":{"mode":"STATIC","address":"10.0.1.2","netmask":"255.255.255.0","gateway":"10.0.1.1"}},"id1":"2","id2":"4"},"keyEncryption":false}},"version":"14"});

function test(data) {
    var valid = validate(data);
    if (valid) console.log('Valid!');
    else console.log('Invalid: ' + ajv.errorsText(validate.errors));
}
@epoberezkin
Copy link
Member

additionalProperties: false makes invalid all properties not present in properties keyword (and not matching patterns in patternProperties) in the SAME subschema.

This schema:

"mgt0": {
              "type": "object",
              "$ref": "#/definitions/interface",
              "additionalProperties": false,
              "required": [
                "mode"
              ]
            }

does not have properties keyword, so any property will be invalid according to spec.

You either need to move properties from #/definitions/interface to this schema or to move additionalProperties: false to #/definitions/interface.

Also, strictly speaking, the standard says that $ref should be the only property present in the object, and you have to use allOf to apply both $ref and some other schema. Ajv is lax here, it doesn't flag $ref together with other keywords as an error. But I would recommend fixing it too. EDITED: It won't affect the way additionalProperties are validated though.

@sashkamal
Copy link
Author

Thanks for the clarification. Since the definition is used in multiple places, Will talk to the team that owns the schema and move the additionalProperties: false and also the "required" section to the #/definition/interface section. I tested by moving and it works as expected.

@epoberezkin
Copy link
Member

Thank you

@sashkamal
Copy link
Author

Also found out that even if you use allOf to apply both $ref and some other schema, additonalProperties: false doesn't work as expected as the JSON schema doesn't support inheritance. So the only way is to replicate the whole properties.

@epoberezkin
Copy link
Member

additionalProperties are indeed always relative to the properties defined in the same subschema (the same object in the schema).

The better approach than to repeat properties though could be to refactor them outside of allOf/other keywords. You can look at the examples in related #129 and #134.

@sashkamal
Copy link
Author

Thanks. It helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants
@epoberezkin @sashkamal and others