carrotstrip
carrotstrip

Reputation: 11

Validating arbitrary dict keys with strict schemas with Cerberus

I am trying to validate JSON, the schema for which specifies a list of dicts with arbitrary string keys, the corresponding values of which are dicts with a strict schema (i.e, the keys of the inner dict are strictly some string, here 'a'). From the Cerberus docs, I think that what I want is the 'keysrules' rule. The example in the docs seems to only show how to use 'keysrules' to validate arbitrary keys, but not their values. I wrote the below code as an example; the best I could do was assume that 'keysrules' would support a 'schema' argument for defining a schema for these values.

keysrules = {
    'myDict': {
        'type': 'dict',
        'keysrules': {
            'type': 'string',
            'schema': {
                'type': 'dict',
                'schema': {
                    'a': {'type': 'string'}
                }
            }
        }
    }
}


keysRulesTest = {
    'myDict': {
        'arbitraryStringKey': {
            'a': 'arbitraryStringValue'
        },
        'anotherArbitraryStringKey': {
            'shouldNotValidate': 'arbitraryStringValue'
        }
    }
}


def test_rules():
    v = Validator(keysrules)
    if not v.validate(keysRulesTest):
        print(v.errors)
        assert(0)

This example does validate, and I would like it to not validate on 'shouldNotValidate', because that key should be 'a'. Does the flexibility implied by 'keysrules' (i.e, keys governed by 'keysrules' have no constraint other than {'type': 'string'}) propagate down recursively to all schemas underneath it? Or have I made some different error? How can I achieve my desired outcome?

Upvotes: 0

Views: 617

Answers (1)

carrotstrip
carrotstrip

Reputation: 11

I didn't want keysrules, I wanted valuesrules:

keysrules = {
    'myDict': {
        'type': 'dict',
        'valuesrules': {
            'type': 'dict',
            'schema': {
                    'a': {'type': 'string'}
            }
        }
    }
}


keysRulesTest = {
    'myDict': {
        'arbitraryStringKey': {
            'a': 'arbitraryStringValue'
        },
        'anotherArbitraryStringKey': {
            'shouldNotValidate': 'arbitraryStringValue'
        }
    }
}


def test_rules():
    v = Validator(keysrules)
    if not v.validate(keysRulesTest):
        print(v.errors)
        assert(0)

This produces my desired outcome.

Upvotes: 1

Related Questions