Validating JSON Schema with Cerberus throws error when using correct data type

565 views Asked by At

I am trying to validate a JSON schema. When specifying the correct data type date for released Cerberus throws an error.

def test_validate_books_schema():
    schema = {
            "url" : {'type': 'string'},
            "name" : {'type': 'string'},
            "isbn" : {'type': 'string'},
            "authors" : {'type': ['string','list']},
            "numberOfPages" : {'type': 'integer'},
            "publisher" : {'type': 'string'},
            "country" : {'type': 'string'},
            "mediaType" : {'type': 'string'},
            "released" : {'type': 'date'},
            "characters" : {'type': ['string','list']},
            "povCharacters" : {'type': ['string','list']}            
        }

    response = requests.get("https://www.anapioficeandfire.com/api/books/1")
    
    v = Validator(schema)
    validate_response = v.validate(response.json())
    assert_that(validate_response, description=v.errors).is_true()
./tests/books/test_books.py::test_validate_books_schema Failed: [undefined]AssertionError: [{'released': ['must be of date type']}] Expected <True>, but was not.
def test_validate_books_schema():
        schema = {
                "url" : {'type': 'string'},
                "name" : {'type': 'string'},
                "isbn" : {'type': 'string'},
                "authors" : {'type': ['string','list']},
                "numberOfPages" : {'type': 'integer'},
                "publisher" : {'type': 'string'},
                "country" : {'type': 'string'},
                "mediaType" : {'type': 'string'},
                "released" : {'type': 'date'},
                "characters" : {'type': ['string','list']},
                "povCharacters" : {'type': ['string','list']}
            }
    
        response = requests.get("https://www.anapioficeandfire.com/api/books/1")
    
        v = Validator(schema)
        validate_response = v.validate(response.json())
>       assert_that(validate_response, description=v.errors).is_true()
E       AssertionError: [{'released': ['must be of date type']}] Expected <True>, but was not.

tests\books\test_books.py:42: AssertionError

The documentation states that the data type for released is Date. When I specify string for released it works.

1

There are 1 answers

2
zedfoxus On BEST ANSWER

Change your code just slightly like so:

from cerberus import Validator
from assertpy import assert_that
from datetime import datetime
import requests

def date_hook(json_dict):
    for (key, value) in json_dict.items():
        try:
            json_dict[key] = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S")
        except:
            pass
    return json_dict

def test_validate_books_schema():
    schema = {
            "url" : {'type': 'string'},
            "name" : {'type': 'string'},
            "isbn" : {'type': 'string'},
            "authors" : {'type': ['string','list']},
            "numberOfPages" : {'type': 'integer'},
            "publisher" : {'type': 'string'},
            "country" : {'type': 'string'},
            "mediaType" : {'type': 'string'},
            "released" : {'type': 'date'},
            "characters" : {'type': ['string','list']},
            "povCharacters" : {'type': ['string','list']}            
        }

    response = requests.get("https://www.anapioficeandfire.com/api/books/1")

    v = Validator(schema)
    validate_response = v.validate(response.json(object_hook=date_hook))
    assert_that(validate_response, description=v.errors).is_true()

test_validate_books_schema()
print('Done')

What we did here is add an object hook in response.json that'll call date_hook, which formats date/time appropriately (see this answer)

Once you run your file, you should not get any error.