You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TLDR; summary: use "unevaluatedProperties": false when inheritance is involved (if using JSON Schema Draft >= 2019-09) to be able to reject unexpected members
the (actually "one among many possibilities") corresponding JSON schema, test.schema.json defining a class TypeA with a propertyA and a class TypeB, extending TypeA, with a propertyB:
$ check-jsonschema --schemafile test.schema.json test_unexpected.json
ok -- validation done
The success of test_unexpected is expected (pun intended). The reason is that by default a JSON schema allows additional properties. You need to use an explicit keyword in a JSON schema to disallow them: additionalProperties: false. That's one of the key thing I wanted for the PROJJSON schema. When there are non-mandatory members, I wanted to be able to catch typos, by rejecting additional properties. That way it would catch someone mispelling "datum_ensemble" as "datum_ensembble" , or putting a lowercase where an uppercase is expected, or forgetting a underscore, or whatever.
And that's where things are tricky. My findings is that inheritance using allOff is fine if used alone, additionalProperties: false is fine if used alone, but if you start combining them together, things break apart.
Let's see by modifying test.schema.json as test_add_properties_false.schema.json with
Now let's validate the doc that has the unexpected member:
$ check-jsonschema --schemafile test_add_properties_false.schema.json test_unexpected.json
Schema validation errors were encountered.
test_unexpected.json::$: Additional properties are not allowed ('propertyA', 'propertyB', 'unexpected' were unexpected)
It gets rejected, but or a wrong reason. It also considers propertyA and propertyB to be unexpected.
OK, let's try with a valid instance:
$ check-jsonschema --schemafile test_add_properties_false.schema.json test.json
Schema validation errors were encountered.
test.json::$: Additional properties are not allowed ('propertyA', 'propertyB' were unexpected)
Same issue. That's not good. So this is not the way to go.
Let's experiment with another approach for test.json.schema. Let's call it test2.json.schema:
$ check-jsonschema --schemafile test2_add_properties_false.schema.json test.json
Schema validation errors were encountered.
test.json::$: Additional properties are not allowed ('propertyA' was unexpected)
$ check-jsonschema --schemafile test2_add_properties_false.schema.json test_unexpected.json
Schema validation errors were encountered.
test_unexpected.json::$: Additional properties are not allowed ('propertyA', 'unexpected' were unexpected)
So things are slightly better in which it doesn't reject anymore propertyB, but it rejects the inherited propertyA.
This is why in projjsonschema, I found out that you have to re-mention inherits member of upper classes. So let's try that and create test_redefine_everything.schema.json with:
$ check-jsonschema --schemafile test_redefine_everything.schema.json test.json
ok -- validation done
$ check-jsonschema --schemafile test_redefine_everything.schema.json test_unexpected.json
Schema validation errors were encountered.
test_unexpected.json::$: Additional properties are not allowed ('unexpected' was unexpected)
Which correlates with the practice in projjson.schema.json, like the following one where geodetic_crs has to mention the members inherited from object_usage:
So let's now slightly edit the original test.schema.json as test_unevaluatedProperties.schema.json by adding a unevaluatedProperties: false member in it:
$ check-jsonschema --schemafile test_unevaluatedProperties.schema.json test_une
test_unevaluatedProperties.schema.json test_unexpected.json
$ check-jsonschema --schemafile test_unevaluatedProperties.schema.json test_unexpected.json
Schema validation errors were encountered.
test_unexpected.json::$: Unevaluated properties are not allowed ('unexpected' was unexpected)
Yes!!! Success. So the Best Practice document should be updated to mention that "unevaluatedProperties": false must be used with inheritance if using JSON Schema Draft >= 2019-09. And this is the key to simplify projjson.schema.json without all the tedious copy&paste bloat I had to do at the time of Draft 07 (PROJJSON was initially released in July 2019)
The text was updated successfully, but these errors were encountered:
Uh oh!
There was an error while loading. Please reload this page.
TLDR; summary: use
"unevaluatedProperties": false
when inheritance is involved (if using JSON Schema Draft >= 2019-09) to be able to reject unexpected membersLong version:
Let's play a bit with the example of "Best Practice for OGC - UML to JSON encoding rules" (https://portal.ogc.org/files/?artifact_id=108010&version=1#toc27), paragraph 7.3.3.4 "Inheritance"
Let's consider:
test.json
containing:test.schema.json
defining a class TypeA with a propertyA and a class TypeB, extending TypeA, with a propertyB:This is a direct copy&paste from the above reference best practice document
Now let's use the check-jsonschema Python utility (using latest version 0.29.2 at time of writing):
Life is good as expected.
Now let's consider a variation of our document with a unexpected property. Let's call it
test_unexpected.json
:Let's validate it:
The success of test_unexpected is expected (pun intended). The reason is that by default a JSON schema allows additional properties. You need to use an explicit keyword in a JSON schema to disallow them:
additionalProperties: false
. That's one of the key thing I wanted for the PROJJSON schema. When there are non-mandatory members, I wanted to be able to catch typos, by rejecting additional properties. That way it would catch someone mispelling "datum_ensemble" as "datum_ensembble" , or putting a lowercase where an uppercase is expected, or forgetting a underscore, or whatever.And that's where things are tricky. My findings is that inheritance using allOff is fine if used alone, additionalProperties: false is fine if used alone, but if you start combining them together, things break apart.
Let's see by modifying test.schema.json as
test_add_properties_false.schema.json
withNow let's validate the doc that has the unexpected member:
It gets rejected, but or a wrong reason. It also considers propertyA and propertyB to be unexpected.
OK, let's try with a valid instance:
Same issue. That's not good. So this is not the way to go.
Let's experiment with another approach for test.json.schema. Let's call it test2.json.schema:
So basically we move the allOf constraint inside typeB
Valid documents still validate:
Now let's add additionalProperties:false in it to create a
test2_add_properties_false.schema.json
schema:Let' s try it:
So things are slightly better in which it doesn't reject anymore propertyB, but it rejects the inherited propertyA.
This is why in projjsonschema, I found out that you have to re-mention inherits member of upper classes. So let's try that and create
test_redefine_everything.schema.json
with:And now we get the expected results!
Which correlates with the practice in projjson.schema.json, like the following one where geodetic_crs has to mention the members inherited from object_usage:
This is why I say that inheritance in JSON schema is not a prime concept.
But... all of that was true in the draf-07 era. draft 2019-09 brings a new keyword, "unevaluatedProperties", which is a kind of "additionalProperties", but that works with inheritance: https://json-schema.org/understanding-json-schema/reference/object#unevaluatedproperties
So let's now slightly edit the original test.schema.json as
test_unevaluatedProperties.schema.json
by adding a unevaluatedProperties: false member in it:And now:
Yes!!! Success. So the Best Practice document should be updated to mention that
"unevaluatedProperties": false
must be used with inheritance if using JSON Schema Draft >= 2019-09. And this is the key to simplify projjson.schema.json without all the tedious copy&paste bloat I had to do at the time of Draft 07 (PROJJSON was initially released in July 2019)The text was updated successfully, but these errors were encountered: