-
Notifications
You must be signed in to change notification settings - Fork 399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invalid extended schema is validated as correct #28
Comments
OK, I can reproduce the bug easily, and on the other hand, I didn't mean the API to be used this way (if you are to define other keywords, you are meant to be defining your own syntax validators and keyword validators). I am still chasing the bug here, but I have one question in the meanwhile: what do you mean "from" to be? An instance keyword or a schema keyword? |
More generally, there is one issue that I am aware of: I do not do recursive schema syntax validation, which means, for instance, with such a schema: {
"properties": {
"p": { "type": null }
}
} I would only trigger a schema validation failure if the instance to validate is an object and has a property with name HOWEVER. You define a new schema keyword here, so the API pretty much expects that you define it, see example 9. I clearly must do recursive schema validation, but on the other hand you can define a new keyword for your needs -- and I just noticed that your extended schema has no definition for I'd appreciate if you expressed your needs a little further? There is probably a way to do what you mean to do using 1.4.x. |
I did a little experience based on example 9. I declared the "indexed" keyword syntax-wise only and schema2 indeed fails to validate: https://gist.github.com/4393138 I believe there are two problems in general:
I do agree that the current API is ungainly; I don't know what to do of this bug, since I cannot "autodetect" new keywords, and especially this |
The main idea behind this test is to create schemas that extends the draft v3 by adding new keywords/properties. {
"$schema" : "schema1",
"type" : "object",
"properties" : {
"from" : {
"type" : "string",
"required" : true,
"indexed" : true
},
"to" : { "type" : "string", "indexed" : true },
"subject" : { "type" : "string" }
}
} And an instance should look like {
"from" : "john.smith",
"to" : "joe.todd",
"subject" : "test"
} So, what I need is the capacity of defining schemas with new properties (extending the drafts) using only the schema definitions. |
OK, so:
There are two main reasons for it:
What you want, basically, is that a JSON file, when injected one way or another, automatically add a new keyword. The problem is that in this case, this can be only added at the syntax level. Let's take your "indexed" keyword as an example: its value is a boolean, OK. But it plays no role in instance validation, right? I had in the plans to make a nicer "schema extension" API, but did not plan to extend it using JSON input -- that would require blurring, and ultimately eliminating, the frontier between syntax and keyword validation. Why not... I just cannot wrap my head around this yet ;) |
Manipulation error... Refer to above comment |
Wrapping up: you say
And by "schema defintions" I understand a JSON file, right? Now, if a programmatical way of doing that, more simple than the gist, were proposed? Say: // New schema definition: must provide new URI; add keywords to it, build it.
// The only possible keyword additions are simple or multiple type syntax checking.
// More complex keywords, and in particular all keywords implying instance checking,
// would have to go the Keyword way.
MetaSchema mySchema = MetaSchema.basedOn(BuiltinSchemas.DRAFTV3_HYPERSCHEMA)
.withURI("your://schema/uri#").withNewKeyword("indexed", NodeType.BOOLEAN).build();
// Create JsonSchemaFactory with this new schema, make it the default (second argument
// to .addMetaSchema() is true)
JsonSchemaFactory factory = new JsonSchemaFactory.Builder()
.addMetaSchema(mySchema, true).build(); would that be OK? As of yet, I am much more at ease with implementing the above than to "heuristically parse" a JSON schema file... |
Unfortunately, I need that on the JSON files. Programmatically won't work for me. |
I am sorry, but:
Why? It does not really make any sense. And:
Please don't. Update to 1.4.x, it fixes quite a few bugs and is MUCH faster than 0.5.x. |
I also insist: please tell me your exact need. I think there is a better way to achieve what you want. Also, since at least 1.0.x, a |
What I need is the following. {
"from" : "john.smith",
"to" : "santa.claus",
"subject" : "Presents",
"date" : "2012/12/21"
} I can easily use the draft v3 or v4 to validate this instance with schema based on draft v3 (or v4). {
"$schema" : "http://json-schema.org/draft-03/schema#",
"id" : "http://example.com/message",
"description" : "e-mail message template",
"type" : "object",
"properties" : {
"date" : { "type" : "string", "format" : "date-time", "required" : true },
"from" : { "type" : "string", "format" : "email", "required" : true },
"to" : { "type" : "string", "format" : "email" }
}
} This is fine. But now, I want to add some new keywords, like 'indexed' for instance. {
"$schema" : "http://json-schema.org/draft-03/schema#",
"id":"http://example.com/my-schema",
"description":"My Extended schema",
"properties":{"indexed":{"type": "boolean"}},
"extends":{"$ref":"http://json-schema.org/draft-03/schema#"}
} And now, I can change the message schema {
"$schema" : "http://example.com/my-schema",
"id" : "http://example.com/message",
"description" : "e-mail message template",
"type" : "object",
"properties" : {
"date" : { "type" : "string", "format" : "date-time", "required" : true, "indexed" : true },
"from" : { "type" : "string", "format" : "email", "required" : true, "indexed" : true },
"to" : { "type" : "string", "format" : "email" }
}
} That changes on schemas (adding new keywords) are made dynamically. |
I fail to understand how that worked with 0.5.x at all: new schema keywords also had to be added programatically... |
I have just understood why you saw your behaviour. Let me explain. In the draft v3 metaschema, the {
"properties": { "additionalProperties": { "$ref": "#" } }
} The As a result, when you try to validate a schema such as: {
"properties": { "from": { "indexed": "meh" } }
} with your extended schema, values of the You therefore want to define your extended schema like this: {
"$schema" : "http://json-schema.org/draft-03/schema#",
"id":"http://example.com/my-schema",
"description":"My Extended schema",
"extends":{"$ref":"http://json-schema.org/draft-03/schema#"},
"properties": {
"indexed": { "type": "boolean" },
"properties": { "additionalProperties": { "$ref": "#" } }
}
} And unfortunately, this only overrides This, or write your extended schema fully, ie take the entire draft v3 schema json file and add your keywords in it. |
Does my explanation make any sense? |
Well, your explanation was not what I was expected. I was expecting a behaviour more like it is defined on the draft for v3, that is, "the behavior of extends can be seen as validating an instance against all constraints in the extending schema as well as the extended schema(s)". And the example on that draft is rather similar to mine... |
There are two things:
The first point means that the The second point means that having, for instance: {
"id": "ref://schema1#",
"properties": { "p": { "type": "boolean" } },
"additionalProperties": false
} and: {
"id": "ref://schema2#",
"extends": { "$ref": "ref://schema1#" },
"properties": { "q": { "type": "boolean" } }
} effectively means that the target instance has to obey both schemas at URIs {
"properties": {
"p": { "type": "boolean" },
"q": { "type": "boolean" }
},
"additionalProperties": false
} This is, unfortunately, a very common misinterpretation of |
I forget to mention that extends definition on draft v3 also talks about in inheritance. In that case, the schema2 should inherit the definition of schema1 and a target instance {
"p" : true,
"q" : false
} should be valid and {
"p" : 123,
"q" : false
} should be invalid. Final result it should be the same, the last target instance is invalid for schema1 but is valid for schema2 |
It talks about inheritance, but not the way you think. It explicitly says that it should be validating instances "against all constraints in the extending schema as well as the extended schema". And schema1 says that there should be no additional property defined than |
I see. Thanks for your clarifications. One more question: if schema1 didn't have additional property as false (additionalProperties : true), both instances still invalid? Or the first becomes valid? |
If |
How the target instances are validated against schema2? What is the validation procedure? |
OK, I'll get into the gory details there, so I beg you to ask questions/source references if there is an obscure point to you. There are three elements:
First, you register your schema (a JSON document) against the registry; this returns a Then the process is as follows (this is step 1):
Once you get hold of the schema node, you go through the validator cache which does two things:
The actual validation happens in the instance validator:
Note that the order of keyword evaluation is completely random. And note that for your particular example, And there is yet more. Believe me, I've had a hard time coming with a fully coherent implementation of all that ;) Reference resolving in particular is quite the devil's job. If you are interested into what happens at this point, you can have a look here: |
Thanks for the explanation, and believe on you about the complexity of the implementation. |
The reason for the change in {
"type": "integer",
"required": true
} Except that The new definition of (an interesting detail about the above: you will note that if you have to validate Hope this helps! |
I agree with you. Thanks for the help. |
Lastest version: 1.4.1
Error explanation:
Code:
The schema1.json file is
The schema2.json is
The text was updated successfully, but these errors were encountered: