Custom media type deserializers

This commit is contained in:
Artur Maciag 2020-02-03 16:30:31 +00:00 committed by p1c2u
parent 80485788c0
commit ab2e10f998
6 changed files with 71 additions and 9 deletions

View file

@ -111,6 +111,31 @@ and unmarshal response data from validation result
Response object should be instance of OpenAPIResponse class (See `Integrations`_).
Customizations
##############
Deserializers
*************
Pass custom defined media type deserializers dictionary with supported mimetypes as a key to `RequestValidator` or `ResponseValidator` constructor:
.. code-block:: python
def protobuf_deserializer(message):
feature = route_guide_pb2.Feature()
feature.ParseFromString(message)
return feature
custom_media_type_deserializers = {
'application/protobuf': protobuf_deserializer,
}
validator = ResponseValidator(
spec, custom_media_type_deserializers=custom_media_type_deserializers)
result = validator.validate(request, response)
Integrations
############

View file

@ -1,4 +1,4 @@
from openapi_core.schema.media_types.util import json_loads
from openapi_core.deserializing.media_types.util import json_loads
from openapi_core.deserializing.media_types.deserializers import (
PrimitiveDeserializer,
@ -11,8 +11,18 @@ class MediaTypeDeserializersFactory(object):
'application/json': json_loads,
}
def __init__(self, custom_deserializers=None):
if custom_deserializers is None:
custom_deserializers = {}
self.custom_deserializers = custom_deserializers
def create(self, media_type):
deserialize_callable = self.MEDIA_TYPE_DESERIALIZERS.get(
media_type.mimetype, lambda x: x)
deserialize_callable = self.get_deserializer_callable(
media_type.mimetype)
return PrimitiveDeserializer(
media_type.mimetype, deserialize_callable)
def get_deserializer_callable(self, mimetype):
if mimetype in self.custom_deserializers:
return self.custom_deserializers[mimetype]
return self.MEDIA_TYPE_DESERIALIZERS.get(mimetype, lambda x: x)

View file

@ -23,9 +23,13 @@ from openapi_core.validation.util import get_operation_pattern
class RequestValidator(object):
def __init__(self, spec, custom_formatters=None):
def __init__(
self, spec,
custom_formatters=None, custom_media_type_deserializers=None,
):
self.spec = spec
self.custom_formatters = custom_formatters
self.custom_media_type_deserializers = custom_media_type_deserializers
def validate(self, request):
try:
@ -187,7 +191,8 @@ class RequestValidator(object):
from openapi_core.deserializing.media_types.factories import (
MediaTypeDeserializersFactory,
)
deserializers_factory = MediaTypeDeserializersFactory()
deserializers_factory = MediaTypeDeserializersFactory(
self.custom_media_type_deserializers)
deserializer = deserializers_factory.create(media_type)
return deserializer(value)

View file

@ -16,9 +16,13 @@ from openapi_core.validation.util import get_operation_pattern
class ResponseValidator(object):
def __init__(self, spec, custom_formatters=None):
def __init__(
self, spec,
custom_formatters=None, custom_media_type_deserializers=None,
):
self.spec = spec
self.custom_formatters = custom_formatters
self.custom_media_type_deserializers = custom_media_type_deserializers
def validate(self, request, response):
try:
@ -112,7 +116,8 @@ class ResponseValidator(object):
from openapi_core.deserializing.media_types.factories import (
MediaTypeDeserializersFactory,
)
deserializers_factory = MediaTypeDeserializersFactory()
deserializers_factory = MediaTypeDeserializersFactory(
self.custom_media_type_deserializers)
deserializer = deserializers_factory.create(media_type)
return deserializer(value)

View file

@ -51,8 +51,9 @@ class TestMediaTypeDeserialise(object):
@pytest.fixture
def deserializer_factory(self):
def create_deserializer(media_type):
return MediaTypeDeserializersFactory().create(media_type)
def create_deserializer(media_type, custom_deserializers=None):
return MediaTypeDeserializersFactory(
custom_deserializers=custom_deserializers).create(media_type)
return create_deserializer
def test_empty(self, deserializer_factory):
@ -69,3 +70,19 @@ class TestMediaTypeDeserialise(object):
result = deserializer_factory(media_type)(value)
assert result == {}
def test_no_schema_custom_deserialiser(self, deserializer_factory):
custom_mimetype = 'application/custom'
media_type = MediaType(custom_mimetype)
value = "{}"
def custom_deserializer(value):
return 'custom'
custom_deserializers = {
custom_mimetype: custom_deserializer,
}
result = deserializer_factory(
media_type, custom_deserializers=custom_deserializers)(value)
assert result == 'custom'