Stranger6667/jsonschema-rs

unexpected draft2019-09 (and up) $ref behavior

Closed this issue · 5 comments

dlowe commented

In draft2019-09, $ref was changed to allow other keywords alongside it.

I ran into this while trying to validate an openapi spec against the published OAS 3.1 schema. In particular, check out the way, in that schema, "$ref": "#/$defs/specification-extensions", is used to factor a common patternProperties out of a bunch of different objects.

Unfortunately, jsonschema doesn't seem to handle the $ref behavior correctly when it has peer keywords. For example:

use jsonschema::{Draft, JSONSchema};
use serde_json::{json, to_string_pretty};

fn main() -> Result<(), std::io::Error> {
    let ok_instance = json!(6);
    let err_instance = json!(7);

    for schema in vec![
        json!({
            "type": "integer",
            "multipleOf": 3,
            "minimum": 6
        }),
        json!({
            "type": "integer",
            "multipleOf": 3,
            "$ref": "#/$defs/mini",
            "$defs": {
                "mini": {
                    "minimum": 6
                }
            }
        }),
    ] {
        let compiled = JSONSchema::options()
            .with_draft(Draft::Draft202012)
            .compile(&schema)
            .expect("A valid schema");

        if compiled.validate(&ok_instance).is_err() {
            println!(
                "instance:\n{}\n... incorrectly *failed* validation against schema:\n{}",
                to_string_pretty(&ok_instance).unwrap(),
                to_string_pretty(&schema).unwrap()
            )
        }

        if compiled.validate(&err_instance).is_ok() {
            println!(
                "instance:\n{}\n... incorrectly *passed* validation against schema:\n{}",
                to_string_pretty(&err_instance).unwrap(),
                to_string_pretty(&schema).unwrap()
            )
        }
    }
    Ok(())
}

fails with:

instance:
7
... incorrectly *passed* validation against schema:
{
  "$defs": {
    "mini": {
      "minimum": 6
    }
  },
  "$ref": "#/$defs/mini",
  "multipleOf": 3,
  "type": "integer"
}

Does that make sense? Have I missed something about the way this is supposed to work?

Hi! You’re right, this is not yet supported for that draft. Drafts after 7th are incomplete at the moment

dlowe commented

Got it. What are the plans? Is this already covered by the json-schema test suite?

I am planning to finish rewriting in #373 first and then continue with all the missing features/changes from newer drafts. Though, I'd be happy to review any PRs for them and merge them earlier, as I think such changes won't be hard to integrate with the new structure later.

However, at the moment I don't have the bandwidth to work on this :(

Re: test suite. It should be there, yep, but likely disabled as of now.

Fixed by #419