Skip to content

Commit ae8e0c9

Browse files
committed
Custom media type deserializers
1 parent 8048578 commit ae8e0c9

File tree

5 files changed

+61
-7
lines changed

5 files changed

+61
-7
lines changed

README.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,28 @@ and unmarshal response data from validation result
111111
Response object should be instance of OpenAPIResponse class (See `Integrations`_).
112112

113113

114+
Customizations
115+
##############
116+
117+
Deserializers
118+
*************
119+
120+
Pass custom defined media type deserializers dictionary with supported mimetypes as a key to `Requestvalidator` constructor:
121+
122+
.. code-block:: python
123+
124+
def protobuf_deserializer(message):
125+
feature = route_guide_pb2.Feature()
126+
feature.ParseFromString(message)
127+
return feature
128+
custom_media_type_deserializers = {
129+
'application/protobuf': protobuf_deserializer,
130+
}
131+
validator = ResponseValidator(
132+
spec, custom_media_type_deserializers=custom_media_type_deserializers)
133+
result = validator.validate(request, response)
134+
135+
114136
Integrations
115137
############
116138

openapi_core/deserializing/media_types/factories.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from openapi_core.schema.media_types.util import json_loads
1+
from openapi_core.deserializing.media_types.util import json_loads
22

33
from openapi_core.deserializing.media_types.deserializers import (
44
PrimitiveDeserializer,
@@ -11,8 +11,18 @@ class MediaTypeDeserializersFactory(object):
1111
'application/json': json_loads,
1212
}
1313

14+
def __init__(self, custom_deserializers=None):
15+
if custom_deserializers is None:
16+
custom_deserializers = {}
17+
self.custom_deserializers = custom_deserializers
18+
1419
def create(self, media_type):
15-
deserialize_callable = self.MEDIA_TYPE_DESERIALIZERS.get(
16-
media_type.mimetype, lambda x: x)
20+
deserialize_callable = self.get_deserializer_callable(
21+
media_type.mimetype)
1722
return PrimitiveDeserializer(
1823
media_type.mimetype, deserialize_callable)
24+
25+
def get_deserializer_callable(self, mimetype):
26+
if mimetype in self.custom_deserializers:
27+
return self.custom_deserializers[mimetype]
28+
return self.MEDIA_TYPE_DESERIALIZERS.get(mimetype, lambda x: x)

openapi_core/validation/request/validators.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@
2323

2424
class RequestValidator(object):
2525

26-
def __init__(self, spec, custom_formatters=None):
26+
def __init__(
27+
self, spec,
28+
custom_formatters=None, custom_media_type_deserializers=None,
29+
):
2730
self.spec = spec
2831
self.custom_formatters = custom_formatters
32+
self.custom_media_type_deserializers = custom_media_type_deserializers
2933

3034
def validate(self, request):
3135
try:
@@ -187,7 +191,8 @@ def _deserialise_media_type(self, media_type, value):
187191
from openapi_core.deserializing.media_types.factories import (
188192
MediaTypeDeserializersFactory,
189193
)
190-
deserializers_factory = MediaTypeDeserializersFactory()
194+
deserializers_factory = MediaTypeDeserializersFactory(
195+
self.custom_media_type_deserializers)
191196
deserializer = deserializers_factory.create(media_type)
192197
return deserializer(value)
193198

tests/unit/deserializing/test_deserialize.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ class TestMediaTypeDeserialise(object):
5151

5252
@pytest.fixture
5353
def deserializer_factory(self):
54-
def create_deserializer(media_type):
55-
return MediaTypeDeserializersFactory().create(media_type)
54+
def create_deserializer(media_type, custom_deserializers=None):
55+
return MediaTypeDeserializersFactory(
56+
custom_deserializers=custom_deserializers).create(media_type)
5657
return create_deserializer
5758

5859
def test_empty(self, deserializer_factory):
@@ -69,3 +70,19 @@ def test_no_schema_deserialised(self, deserializer_factory):
6970
result = deserializer_factory(media_type)(value)
7071

7172
assert result == {}
73+
74+
def test_no_schema_custom_deserialiser(self, deserializer_factory):
75+
custom_mimetype = 'application/custom'
76+
media_type = MediaType(custom_mimetype)
77+
value = "{}"
78+
79+
def custom_deserializer(value):
80+
return 'custom'
81+
custom_deserializers = {
82+
custom_mimetype: custom_deserializer,
83+
}
84+
85+
result = deserializer_factory(
86+
media_type, custom_deserializers=custom_deserializers)(value)
87+
88+
assert result == 'custom'

0 commit comments

Comments
 (0)