jsonschema-rs icon indicating copy to clipboard operation
jsonschema-rs copied to clipboard

unexpected draft2019-09 (and up) $ref behavior

Open dlowe opened this issue 2 years ago • 4 comments

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?

dlowe avatar Jun 07 '22 22:06 dlowe

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

Stranger6667 avatar Jun 07 '22 22:06 Stranger6667

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

dlowe avatar Jun 07 '22 22:06 dlowe

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 :(

Stranger6667 avatar Jun 08 '22 07:06 Stranger6667

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

Stranger6667 avatar Jun 08 '22 07:06 Stranger6667

Fixed by #419

Stranger6667 avatar Mar 16 '23 07:03 Stranger6667