json-schema-validator icon indicating copy to clipboard operation
json-schema-validator copied to clipboard

Walk Listeners not working for 2019-09 meta schema

Open dustinhiatt-wf opened this issue 4 years ago • 5 comments

If I take the following simple schema definition:

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "type": "object",
  "properties": {
    "kebab-case": {
      "type": "string"
    },
    "snake_case": {
      "type": "string"
    },
    "a": {
      "type": "string"
    }
  }
}

And I attempt to load up the 2019 meta schema:

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "$id": "https://json-schema.org/draft/2019-09/schema",
  "$vocabulary": {
    "https://json-schema.org/draft/2019-09/vocab/core": true,
    "https://json-schema.org/draft/2019-09/vocab/applicator": true,
    "https://json-schema.org/draft/2019-09/vocab/validation": true,
    "https://json-schema.org/draft/2019-09/vocab/meta-data": true,
    "https://json-schema.org/draft/2019-09/vocab/format": false,
    "https://json-schema.org/draft/2019-09/vocab/content": true
  },
  "$recursiveAnchor": true,

  "title": "Core and Validation specifications meta-schema",
  "allOf": [
    {"$ref": "meta/core"},
    {"$ref": "meta/applicator"},
    {"$ref": "meta/validation"},
    {"$ref": "meta/meta-data"},
    {"$ref": "meta/format"},
    {"$ref": "meta/content"}
  ],
  "type": ["object", "boolean"],
  "properties": {
    "definitions": {
      "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.",
      "type": "object",
      "additionalProperties": { "$recursiveRef": "#" },
      "default": {}
    },
    "dependencies": {
      "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"",
      "type": "object",
      "additionalProperties": {
        "anyOf": [
          { "$recursiveRef": "#" },
          { "$ref": "meta/validation#/$defs/stringArray" }
        ]
      }
    }
  }
}

And I construct a factory as follows:

final var factory = JsonSchemaFactory.getInstance(version);
final var config = new SchemaValidatorsConfig();

config.addKeywordWalkListener(ValidatorTypeCode.PROPERTIES.name(), jsonSchemaWalkListener);
return factory.getSchema(JsonSchemaUtil.class.getResourceAsStream(path), config);

Where jsonSchemaWalkListener simply gathers up all properties using getAt, notice that the walker is not called on all properties of the schema being validator. I do not see this behavior with the previous drafts. I am curious if this has to do with vocabularies.

dustinhiatt-wf avatar Aug 30 '21 14:08 dustinhiatt-wf

Validation itself is also being impacted. Loading up the 2019 meta schema spec and using it to validate the following payload returns no error messages:

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "type": "object",
  "properties": {
    "kebab-case": {
      "type": "random"
    },
    "snake_case": {
      "type": "string"
    },
    "a": {
      "type": "string"
    }
  }
}

The first property should return a validation error and using the exact same logic with the same schema but draft-07 will correctly return 2 validation errors.

dustinhiatt-wf avatar Aug 30 '21 14:08 dustinhiatt-wf

@dustinhiatt-wf I am guessing that some of the 2019 new validators don't have the walking method implemented. Do you know the root cause?

stevehu avatar Sep 02 '21 12:09 stevehu

@stevehu stepping through the code, the vocabularies aren't being pulled in before the validators are examining their "sections" to determine what schemas exist to validate. If I take the schema I posted earlier and examine this line: https://github.com/networknt/json-schema-validator/blob/master/src/main/java/com/networknt/schema/PropertiesValidator.java#L52

The schemas map has all the entries you'd expect. The 2019-09 version only includes the two properties in the base 2019-09 metaschema. Essentially, the validation logic is running while ignoring the allOf that should pull in the other vocabularies. I believe what we'd need to modify is here: https://github.com/networknt/json-schema-validator/blob/master/src/main/java/com/networknt/schema/PropertiesValidator.java#L52

In that context that this is running in, the read method won't see any properties from the vocabularies imported by allOf.

dustinhiatt-wf avatar Sep 02 '21 13:09 dustinhiatt-wf

@dustinhiatt-wf As far as my understanding we currently don't have the logic at place to pull the vocabularies on the fly. One approach I follow is to download all the vocabularies and assemble/collate the metaschema locally and then validate the schema against it.

prashanthjos avatar Oct 26 '21 15:10 prashanthjos

@dustinhiatt-wf The other member @ericbroda raised the same issue for the meta schema loading for the 2019-09 and I have created a test case in a separate branch to reproduce it.

https://github.com/networknt/json-schema-validator/issues/475

stevehu avatar Oct 27 '21 04:10 stevehu