"oneOf"
Closed this issue · 8 comments
Hi,
did anyone here ever need "oneOf" from the JSON Schema specification (http://json-schema.org/example2.html)?
validictory does not support that yet, am I right?
Thanks,
Daniel
looks like this is just a special case of $ref - which is not supported as it introduces the idea of loading from loading remote files that I don't think make sense for a validator of python objects.
I think that $ref and the remote resource problems that come with that can be preprocessed before validation and then a little wrapper could solve the problem.
Why is it a special case of ref?
I implemented a solution for "anyOf", it looks like this:
def check_xOf_schema(fieldname, xOf):
if isinstance(xOf, (list, tuple)):
for possibleSchemaMatch in xOf:
if not isinstance(possibleSchemaMatch, dict):
raise SchemaError("Error in {}: Expected {} to only contain objects".format(fieldname, xOf))
else:
raise SchemaError("Properties definition of field '{}' is "
"not a list".format(fieldname))
def validate_anyOf(self, x, fieldname, schema, path, anyOf=None):
'''
Validates that the value of the given field matches any of the defined
schemas
'''
value = x.get(fieldname, None)
if value is not None:
check_xOf_schema(fieldname=fieldname, xOf=anyOf)
matches = []
for index, possibleSchemaMatch in enumerate(anyOf):
try:
self.__validate("_data", {"_data": value}, possibleSchemaMatch,
'{}[{}]'.format(path, index))
matches.append(index)
except FieldValidationError:
pass
if not matches:
raise FieldValidationError(
fieldname=fieldname,
value=value,
message='Must match anyOf {}'.format(anyOf)
)
check_xOf_schema is a global method.
oneOf is quite similar:
def validate_oneOf(self, x, fieldname, schema, path, oneOf=None):
'''
Validates that the value of the given field matches exactly one of the
defined schemas
'''
value = x.get(fieldname, None)
if value is not None:
check_xOf_schema(fieldname=fieldname, xOf=oneOf)
matches = []
for index, possibleSchemaMatch in enumerate(oneOf):
try:
self.__validate("_data", {"_data": value}, possibleSchemaMatch,
'{}[{}]'.format(path, index))
matches.append(index)
except FieldValidationError:
pass
if len(matches) != 1:
raise FieldValidationError(
fieldname=fieldname,
value=value,
message='Must match exactly oneOf {}'.format(oneOf)
)
And allOf also:
def validate_allOf(self, x, fieldname, schema, path, allOf=None):
'''
Validates that the value of the given field matches all of the defined
schemas
'''
value = x.get(fieldname, None)
if value is not None:
check_xOf_schema(fieldname=fieldname, xOf=allOf)
matches = []
for index, possibleSchemaMatch in enumerate(allOf):
try:
self.__validate("_data", {"_data": value}, possibleSchemaMatch,
'{}[{}]'.format(path, index))
matches.append(index)
except FieldValidationError:
pass
print('matches', matches)
if len(matches) != len(allOf):
raise FieldValidationError(
fieldname=fieldname,
value=value,
message='Must match allOf {}'.format(allOf)
)
For my personal taste of clean code this is too much duplicate code but at least anyOf and oneOf passes all the test cases defined in JSON-Schema-Test-Suite.
allOf does not pass all the tests but first things first:
I only have use for "anyOf" in my projects, that's what I realized during this. -->
- How do you like the implementation?
- Which features of the specification should become part of validictory and where do we write down why we ignore the other features?
Side note: "multipleOf" has nothing to do with the other "xOf" cases which is also confusing to me.
if this is passing the inclusion is fine with me, what is failing in allOf?
+1 --- $ref can refer to other "sub-schemas" inside the overall schema document (not external loading) and use those with any/all/oneOf to build more complex extensions. Sayt I have three different types that all look the same except for a few differences based on one property value... I could define the "base schema" in a $ref and then build on it to create other schemas: http://spacetelescope.github.io/understanding-json-schema/structuring.html#extending
apologies if this is already possible in Validictory and I just missed it...
@NickFranceschina Thanks for the link.
validictory today ignores "$ref" because you can actually preprocess your schema before you validate it. In #20 I linked to a small function I wrote to solve the refs before validating: https://github.com/dmr/validictory_preprocess_ref. This is how I solve the "$ref" problem.
This issue here is more about "oneOf" and other special things or where did I miss your question?