swaggest / php-json-schema

High definition PHP structures with JSON-schema based validation
MIT License
446 stars 50 forks source link

Unrecognized types appear to stop validation of other types, should throw exception? #116

Closed jmauerhan closed 3 years ago

jmauerhan commented 3 years ago

When my schema contains some invalid property definition, the validation works up until that point, then stops validating. This is confusing because if one property is defined incorrectly, there is no indication of the actual problem, and makes it appear as if an invalid JSON instance actually validates, when the problem is really in the schema.

Given this simple schema:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Parent",
  "type": "object",
  "required": [
    "title",
    "child"
  ],
  "properties": {
    "title": {
      "type": "string"
    },
    "child": {
      "type": "object",
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "type": "string"
        }
      }
    }
  }
}

When using the Schema::in functionality, the validation works. This example throws an exception, as I expected:

Required property missing: title, data: [] at #->$ref[schema/example.schema.json]->properties:child


$eventJson = <<<EVENT
{
"title":"Test",
"child":{}
}
EVENT;
$data = json_decode($eventJson);

$schema = Schema::import('schema/example.schema.json'); $schema->in($data);


But if I add a property which has a type not actually included in the schema definition such as "uri" or "date-time", I get no exception or errors. For example, using this schema gives me no errors for the `child` property, but it *does* throw an exception if `title` is missing. This is confusing because the tool appears to be working correctly for `title` and not `child`, when the problem is actually that the schema itself is invalid. 

{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Parent", "type": "object", "required": [ "title", "child" ], "properties": { "title": { "type": "string" }, "second_prop": { "type": "uri" }, "child": { "type": "object", "required": [ "title" ], "properties": { "title": { "type": "string" } } } } }


If I fix the actual schema to use `format`, it works again as expected.

{ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Parent", "type": "object", "required": [ "title", "child" ], "properties": { "title": { "type": "string" }, "second_prop": { "type": "string", "format":"uri" }, "child": { "type": "object", "required": [ "title" ], "properties": { "title": { "type": "string" } } } } }



I think either `import` or `in` should throw some exception about the invalid type, rather than silently accepting everything else after it.
vearutop commented 3 years ago

Thank you for filing this issue.

The issue happens when schema is imported from a file (or URI).

Such code would fail with an exception.

$schemaData = json_decode('{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "Parent",
  "type": "object",
  "required": [
    "title",
    "child"
  ],
  "properties": {
    "title": {
      "type": "string"
    },
    "second_prop": {
      "type": "uri"
    },
    "child": {
      "type": "object",
      "required": [
        "title"
      ],
      "properties": {
        "title": {
          "type": "string"
        }
      }
    }
  }
}');

Schema::import($schemaData); // Fails with exception.

But this code would not fail with an exception.

Schema::import($pathToSchemaFile); // Same schema in file.

It is caused by an error-tolerant mode while dereferencing schemas.

vearutop commented 3 years ago

Please try v0.12.32.