Sir Neuman
Sir Neuman

Reputation: 1425

In Cerberus can you use 'valueschema' with a type of 'dict'?

So I'm using Cerberus for schema validation, but I'm running into a particular with validating a subdictionary of a dictionary whose key is unknown.

So say I have the following document:

dict = {
   'things': {
       '0463': {
           'foo': 'blah',
           'bar': 'bleep'
        },
        '0464': {
           'foo': 'x',
           'bar': 'y'
        },
        'another_random_id': {
           'foo': 'blah',
           'bar': 'bleep'
        }
}

So i want to validate that the subdictionaries have a specific structure (foo and bar as keys), but I can't figure out a way to validate this without knowing the keys ahead of time (which in my case are random id's. I figured this was a good use of valueschema but i can't seem to get valueschema to work with something of type 'dict'. I tried to set the following schema in cerberus:

schema = {
    'things': {
        'type': 'dict',
        'valueschema': {
             'type': 'dict',
             'foo': {'type': 'string'},
             'bar': {'type': 'string'}
         }
     }
}

Am i defining my schema incorrectly or is this not possible with the current implementation of valueschema. I saw some tests in the repository that used valueschema, but they were only testing where the type of valueschema was an int or a string.

Upvotes: 4

Views: 2713

Answers (1)

Sir Neuman
Sir Neuman

Reputation: 1425

So I figured out that cerberus will handle valueschema if it's of type dict if I put a schema field after the valueschema key. So my structure should be:

schema = {
    'things': {
        'type': 'dict',
        'valueschema': {
             'type': 'dict',
             'schema':{
                 'foo': {'type': 'string'},
                 'bar': {'type': 'string'}
             }
         }
     }
}

Now there's still some weirdness because it doesn't seem like valueschema was designed with the expectation that it would validate a value of type dict. For example when I extend from the validator, I had to override the validate_valueschema method so that the required validation acts the same as it would for a regular schema, because when it calls validate on the schema it doesn't pass in the update parameter. So my overridden validate_valueschema looks like this:

def _validate_valueschema(self, schema, field, value):
    if isinstance(value, Mapping):
        for key, document in value.items():
            validator = self._Validator__get_child_validator()
            validator.validate(
                {key: document}, {key: schema}, 
                context=self.document, update=self.update)
            if len(validator.errors):
                self._error(field, validator.errors)

The update=self.update is all I added.

Upvotes: 4

Related Questions