voxpupuli / json-schema

Ruby JSON Schema Validator
MIT License
1.53k stars 242 forks source link

file $ref in relative $ref always raises "property #/soandso/0 was not a valid schema" #299

Open Aeva opened 8 years ago

Aeva commented 8 years ago

Hi - I think this might be an instance of #190, but I'm not sure. I apologize if it is a duplicate.

The gist is that when I have a $ref to somewhere within the file, if the object described has a $ref to another schema, then the same error is always thrown regardless of if the file is valid or not.

To demonstrate this, I have this script:

require 'json'
require 'json-schema'

schema = JSON.load <<-END_JSON
{
  "defs" : {
    "this_works_ok" : {
      "item" : "number"
    },
    "this_fails" : {
      "$ref" : "test_schema.json"
    },
    "some_contrived_schema": {
      "type" : "object",
      "properties" : {
        "entities" : {
          "type": "array",
          "items" : { "$ref" : "#/defs/this_works_ok" }
        }
      }
    }
  },

  "allOf" : [
    { "$ref" : "#/defs/some_contrived_schema" }
  ]
}
END_JSON

data = JSON.load <<-END_JSON
{ "entities" : [1,2,3,4] }
END_JSON

errors = JSON::Validator.fully_validate(schema, data, strict: true)
puts errors

And this external schema saved as "test_schema.json":

{
  "item" : "number"
}

The above runs ok, but if you change

"$ref" : "#/defs/this_works_ok"

to

"$ref" : "#/defs/this_fails"

Then the following error is produced:

The property '#/' of type Hash did not match all of the required schemas. The schema specific errors were:

- allOf #0:
    - The property '#/entities/3' was not a valid schema
    - The property '#/entities/2' was not a valid schema
    - The property '#/entities/1' was not a valid schema
    - The property '#/entities/0' was not a valid schema

Interestingly, it throws that error regardless of if the file path is valid or not.

The above is kind of contrived, but demonstrates the problem I'm running into - the schemas I'm trying to use 'allOf' to combine schemas together so that parts of them can be re-used elsewhere. The ref within the 'allOf' then points within that file to any new behavior, and objects that would be list items are broken out into their own files as well. If there is another way to express file paths that would validate, or if there is another approach to structuring this, that would be very helpful.

Thanks for taking the time to consider the above.

iainbeeston commented 8 years ago

Wow that's an interesting example. It does look like it's getting confused while following refs doesn't it? The example is helpful and should allow me to reproduce the problem in a test and then I can fix it from there. I'll let you know how it goes...

ludwick commented 8 years ago

I think I hit this. I was able to get around it by loading the shared / referenced schema file (using JSON::Validator.add_schema). I had to make sure the file reference was the same. In my case it is a long file:some_dir/dir2/file.json and had to make sure the URI as given when creating the schema to load was the same as what is used in the schemas that used it. But that made it work.

Aeva commented 8 years ago

ludwick: my work around was to construct my schemas such that if you make a relative reference to an object, that object does not make a file reference. References to files that themselves contain relative references work fine.