3

I'm using the python jsonschema https://python-jsonschema.readthedocs.io/en/latest/ and I'm trying to find how to use default values and remove additional fields when found.

anyone know how am I suppose to do it? or maybe have another solution to validate jsonschema that supports default values and remove any additional field (like js avj)?

Elon Salfati
  • 1,537
  • 6
  • 23
  • 46
  • How a library uses `default` is not defined by JSON Schema, so the behaviour is not universal. What do you mean by "remove additional fields"? What are you trying to do with JSON Schema beyond validating your JSON? – Relequestual Mar 07 '18 at 10:40
  • The python package you mention has a bit about `default` in their FAQ: https://python-jsonschema.readthedocs.io/en/latest/faq/#why-doesn-t-my-schema-s-default-property-set-the-default-on-my-instance It looks like they expose the ability to customise your validation code to do something with `default`. – Relequestual Mar 07 '18 at 10:42
  • beside the validation I want it to set defaults and remove any additional field that were given for eample if the schema says that only a, b are a known properties then if i get a document {'a':'a', 'b':'b', 'c' :'c'} - then c will be removed – Elon Salfati Mar 07 '18 at 14:09
  • What you're asking for is beyond what JSON Schema is for. You'll have to hook into the validator as per the FAQ link in my previous comment. The normal use for JSON Schema is never to modify the instance. Does that all make sense to you? – Relequestual Mar 07 '18 at 14:12

1 Answers1

6

Hidden in the FAQs you'll find this

Why doesn’t my schema’s default property set the default on my instance? The basic answer is that the specification does not require that default actually do anything.

For an inkling as to why it doesn’t actually do anything, consider that none of the other validators modify the instance either. More importantly, having default modify the instance can produce quite peculiar things. It’s perfectly valid (and perhaps even useful) to have a default that is not valid under the schema it lives in! So an instance modified by the default would pass validation the first time, but fail the second!

Still, filling in defaults is a thing that is useful. jsonschema allows you to define your own validator classes and callables, so you can easily create an jsonschema.IValidator that does do default setting. Here’s some code to get you started. (In this code, we add the default properties to each object before the properties are validated, so the default values themselves will need to be valid under the schema.)

from jsonschema import Draft4Validator, validators


def extend_with_default(validator_class):
    validate_properties = validator_class.VALIDATORS["properties"]

    def set_defaults(validator, properties, instance, schema):
        for property, subschema in properties.iteritems():
            if "default" in subschema:
                instance.setdefault(property, subschema["default"])

        for error in validate_properties(
            validator, properties, instance, schema,
        ):
            yield error

    return validators.extend(
        validator_class, {"properties" : set_defaults},
    )


DefaultValidatingDraft4Validator = extend_with_default(Draft4Validator)


# Example usage:
obj = {}
schema = {'properties': {'foo': {'default': 'bar'}}}
# Note jsonschem.validate(obj, schema, cls=DefaultValidatingDraft4Validator)
# will not work because the metaschema contains `default` directives.
DefaultValidatingDraft4Validator(schema).validate(obj)
assert obj == {'foo': 'bar'}

From: https://python-jsonschema.readthedocs.io/en/latest/faq/#why-doesn-t-my-schema-s-default-property-set-the-default-on-my-instance

TomDotTom
  • 6,238
  • 3
  • 41
  • 39