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

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.



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 zedfoxus