Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
############

Expand Down
16 changes: 13 additions & 3 deletions openapi_core/deserializing/media_types/factories.py
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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)
9 changes: 7 additions & 2 deletions openapi_core/validation/request/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@

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:
Expand Down Expand Up @@ -187,7 +191,8 @@ def _deserialise_media_type(self, media_type, value):
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)

Expand Down
9 changes: 7 additions & 2 deletions openapi_core/validation/response/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@

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:
Expand Down Expand Up @@ -112,7 +116,8 @@ def _deserialise_media_type(self, media_type, value):
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)

Expand Down
21 changes: 19 additions & 2 deletions tests/unit/deserializing/test_deserialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -69,3 +70,19 @@ def test_no_schema_deserialised(self, deserializer_factory):
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'