I am seeing some very strange validation behavior while testing my python eve API.
- Eve 0.7.4
- Mongod v3.2.10
Simplified summary: I have a domain endpoint test
with a schema containing an object props
which has two sub properties time
and wetBulb
DOMAIN = {
# test end point
'test': {
'schema': {
'props': {
'type': 'dict',
'schema': {
'time': {'type': 'datetime'}, # datetime fails to validate
'wetBulb': {'type': ['string', 'float']} # only see issue while key is camel case and contains two type options
}
}
},
'resource_methods': ['GET', 'POST']
}
}
DATE_FORMAT = '%Y-%m-%d %H:%M:%S' # date format seems to be irrelevant
When I define wetBulb
as a camel case key ( i.e. wetBulb
instead of wet_bulb
) AND/OR define it as one of two potential types (i.e. 'type': ['string', 'float']
), eve/cerberus fails to interpret my time
value as a datetime
.
Example:
Running locally with all other defaults, I test this API point using the requests
library:
import requests
post = {
'properties': {
'time': '2017-09-05 20:17:40',
'wetBulb': '21.200000000000003'
}
}
r = requests.post('http://127.0.0.1:5000/test', data=json.dumps(post), headers={'content-type': 'application/json'})
# print response
print('Status {0}'.format(r.status_code))
print(r.text)
and I get the response
Status 422
{"_status": "ERR", "_issues": {"properties": {"time": "must be of datetime type"}}, "_error": {"message": "Insertion failure: 1 document(s) contain(s) error(s)", "code": 422}}
If i change my schema definition to have the key wet_bulb
AND/OR I change its type to 'type': 'string'
it will properly validate:
DOMAIN = {
# test end point
'test': {
'schema': {
'props': {
'type': 'dict',
'schema': {
'time': {'type': 'datetime'},
'wet_bulb': {'type': 'string'}
}
}
},
'resource_methods': ['GET', 'POST']
}
}
then post the object with the updated object:
post = {
'properties': {
'time': '2017-09-05 20:17:40',
'wet_bulb': '21.200000000000003'
}
}
r = requests.post('http://127.0.0.1:5000/test', data=json.dumps(post), headers={'content-type': 'application/json'})
# print response
print('Status {0}'.format(r.status_code))
print(r.text)
Status 201
{"_updated": "2017-09-06 12:30:18", "_links": {"self": {"href": "vos/59afea5aa8a548256898cc40", "title": "Vo"}}, "_created": "2017-09-06 12:30:18", "_status": "OK", "_id": "59afea5aa8a548256898cc40", "_etag": "f1b918a2fe688941f84f4d00bc1b400abddab446"}
Question:
Has anyone seen other behavior like this or can help clarify what may be controlling this validation behavior? I have probed around to try and define what causes the validation but haven't been successful.
EDIT
I believe part of the explanation lies within the two notes below type
in the cerberus documentation, but I still haven't figured out the cause:
http://docs.python-cerberus.org/en/stable/validation-rules.html#type
I am having the same datetime
validation problem in a different schema. In this case I worked around it by either removing the 'type'
declaration or setting 'type'
to be a string instead of a list (i.e. 'type': 'number'
instead of 'type': ['number', 'list']
. Unfortunately this schema won't work for the application so I've removed the 'type'
declaration for now.
You are not sending an actual Python datetime in your JSON. Cerberus date type is to check that the property value is a Python datetime object. So you want to validate a json string and then convert it to a Python datetime. You have two approaches as described here: https://stackoverflow.com/a/61320357/1417256.